最近有时间研究了一下RecyclerView,果然功能强大啊,能实现的效果还是比较多的,那么今天给大家介绍一个用RecyclerView实现的瀑布流效果。

先来一张效果图:



看看怎么实现吧:

整体工程目录结构:

这里要特别强调一点,有人可能不知道去哪里找android-support-v7-recyclerview.jar这个文件,其实它就在你下载的sdk目录下,我的是在D:\Program Files\Android\android-sdk\extras\android\support\v7\recyclerview\libs,直接把这个文件拷贝到自己工程libs目录下即可。不建议在网上找这个jar包,可能会由于版本问题不能使用。

要使用RecyclerView,和ListView一样,先在布局文件中引用:


activity_main.xml

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="#000000"
  6. android:orientation="vertical"
  7. tools:context="com.example.recyclerview_waterfall.MainActivity" >
  8. <LinearLayout
  9. android:layout_width="match_parent"
  10. android:layout_height="48dp"
  11. android:gravity="right">
  12. <ImageView
  13. android:id="@+id/add"
  14. android:layout_width="24dp"
  15. android:layout_margin="12dp"
  16. android:layout_height="24dp"
  17. android:src="@drawable/add" />
  18. </LinearLayout>
  19. <android.support.v7.widget.RecyclerView
  20. android:id="@+id/lv"
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content" />
  23. </LinearLayout>

上面是主布局文件,再看看Item的布局文件:


  1. <?xml version="1.0" encoding="utf-8"?>
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:padding="1dp"
  5. android:layout_height="wrap_content" >
  6. <ImageView
  7. android:id="@+id/iv"
  8. android:layout_width="match_parent"
  9. android:layout_height="wrap_content"
  10. android:background="#B0E0E6"
  11. android:src="@drawable/ic_launcher" />
  12. <TextView
  13. android:id="@+id/tv"
  14. android:layout_width="match_parent"
  15. android:layout_height="wrap_content"
  16. android:background="@null"
  17. android:textSize="18sp" />
  18. </FrameLayout>

item布局文件中就两样东西,一个TextView,一张图片。使用FrameLayout让两个空间重叠在一起。

好了,布局说完了就该说MainActivity了,毫无疑问,先要初始化RecyclerView:

  1. rv = (RecyclerView) findViewById(R.id.lv);
  2. rv.setHasFixedSize(true);
  3. StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(
  4. 3, StaggeredGridLayoutManager.VERTICAL);
  5. rv.setLayoutManager(layoutManager);

使用StaggeredGridLayoutManager来实现瀑布流效果,它的构造方法中有两个参数,第一个是每行显示几个item,第二个参数是滚动的方向。

RecyclerView初始化完成之后我们就该初始化模拟数据了:

  1. /**
  2. * 初始化模拟数据
  3. */
  4. private void initData() {
  5. list = new ArrayList<String>();
  6. ivs = new ArrayList<Integer>();
  7. heights = new ArrayList<Integer>();
  8. for (int i = 'A'; i <= 'Z'; i++) {
  9. list.add("" + (char) i);
  10. heights.add((int) (100 + Math.random() * 300));
  11. }
  12. ivs.add(R.drawable.p1);
  13. ivs.add(R.drawable.p2);
  14. ivs.add(R.drawable.p3);
  15. ivs.add(R.drawable.p4);
  16. ivs.add(R.drawable.p5);
  17. ivs.add(R.drawable.p6);
  18. ivs.add(R.drawable.p7);
  19. ivs.add(R.drawable.p8);
  20. ivs.add(R.drawable.p9);
  21. ivs.add(R.drawable.p10);
  22. ivs.add(R.drawable.p11);
  23. ivs.add(R.drawable.p12);
  24. ivs.add(R.drawable.p13);
  25. ivs.add(R.drawable.p14);
  26. ivs.add(R.drawable.p15);
  27. ivs.add(R.drawable.p16);
  28. ivs.add(R.drawable.p17);
  29. ivs.add(R.drawable.p18);
  30. ivs.add(R.drawable.p19);
  31. ivs.add(R.drawable.p20);
  32. ivs.add(R.drawable.p21);
  33. ivs.add(R.drawable.p22);
  34. ivs.add(R.drawable.p23);
  35. ivs.add(R.drawable.p24);
  36. ivs.add(R.drawable.p25);
  37. ivs.add(R.drawable.p26);
  38. DisplayMetrics dm = new DisplayMetrics();
  39. getWindowManager().getDefaultDisplay().getMetrics(dm);
  40. mScreenWidth = dm.widthPixels;
  41. }

这里主要有四个数据要初始化:

list表示TextView上显示的数据

ivs表示ImageView上显示图片的id

heights表示每个item的高,因为瀑布流中item高度不一,所以我们通过随机数来设定不同的高度。

最后一个mScreenWidth表示屏幕的宽度,我们要根据每行显示几个item来动态设定每个item的宽度。

做完这些就可以new一个Adapter了:

  1. public class WaterFallAdapter extends Adapter {
  2. private Context context;
  3. private List<String> list;
  4. private LayoutInflater layoutInflater;
  5. private List<Integer> heights;
  6. private List<Integer> ivs;
  7. private int mScreenWidth;
  8. public OnItemClickListener listener;
  9. public interface OnItemClickListener {
  10. void onItemClick(View v, int position);
  11. void onItemLongClick(View v, int position);
  12. }
  13. public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
  14. this.listener = onItemClickListener;
  15. }
  16. public WaterFallAdapter(Context context, List<String> list,
  17. List<Integer> heights, List<Integer> ivs, int mScreenWidth) {
  18. this.context = context;
  19. this.list = list;
  20. this.heights = heights;
  21. this.ivs = ivs;
  22. this.mScreenWidth = mScreenWidth;
  23. layoutInflater = LayoutInflater.from(context);
  24. }
  25. @Override
  26. public int getItemCount() {
  27. return ivs.size();
  28. }
  29. @Override
  30. public void onBindViewHolder(ViewHolder viewHolder, final int position) {
  31. final MyViewHolder vHolder = (MyViewHolder) viewHolder;
  32. LayoutParams tvLp = vHolder.tv.getLayoutParams();
  33. tvLp.height = heights.get(position);
  34. tvLp.width = mScreenWidth / 3;
  35. vHolder.tv.setLayoutParams(tvLp);
  36. vHolder.tv.setText(list.get(position));
  37. vHolder.iv.setLayoutParams(tvLp);
  38. vHolder.iv.setImageResource(ivs.get(position));
  39. vHolder.iv.setOnClickListener(new OnClickListener() {
  40. @Override
  41. public void onClick(View v) {
  42. int position2 = vHolder.getPosition();
  43. listener.onItemClick(v, position2);
  44. }
  45. });
  46. vHolder.iv.setOnLongClickListener(new OnLongClickListener() {
  47. @Override
  48. public boolean onLongClick(View v) {
  49. int position2 = vHolder.getPosition();
  50. listener.onItemLongClick(v, position2);
  51. return true;
  52. }
  53. });
  54. }
  55. @Override
  56. public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int pos) {
  57. View v = layoutInflater.inflate(R.layout.item, null);
  58. ViewHolder vh = new MyViewHolder(v);
  59. return vh;
  60. }
  61. public static class MyViewHolder extends RecyclerView.ViewHolder {
  62. public TextView tv;
  63. public ImageView iv;
  64. public MyViewHolder(View itemView) {
  65. super(itemView);
  66. tv = (TextView) itemView.findViewById(R.id.tv);
  67. iv = (ImageView) itemView.findViewById(R.id.iv);
  68. }
  69. }
  70. }

RecyclerView中我们使用ViewHolder时要继承RecyclerView.ViewHolder,在这里初始化item,至于回收防止多次实例化等等都由RecyclerView来完成。onBindViewHolder是我们赋值的方法,在这里我们把数据匹配给item去显示。这里我们根据屏幕的宽度动态设置每个item的宽度。

RecyclerView最大的一个缺陷是没有提供点击事件,所以如果有需要的话要我们自己定义一个接口来完成这个动作。代码如上,我们在很多自定义View中都可以看到类似的方式。

定义好事件点击接口后,我们就可以在MainActivity中调用了:

  1. myAdapter.setOnItemClickListener(new OnItemClickListener() {
  2. @Override
  3. public void onItemLongClick(View v, int position) {
  4. Toast.makeText(MainActivity.this, position + "--long click",
  5. Toast.LENGTH_SHORT).show();
  6. list.remove(position);
  7. ivs.remove(position);
  8. myAdapter.notifyItemRemoved(position);
  9. }
  10. @Override
  11. public void onItemClick(View v, int position) {
  12. Toast.makeText(MainActivity.this, position + "--click",
  13. Toast.LENGTH_SHORT).show();
  14. }
  15. });

点击直接弹出一个Toast,长按删除该项,删除的时候系统有自带动画,当然我们也可以自定义删除动画。删除之后我们使用myAdapter.notifyItemRemoved(position);而不是使用notifyDataSetChanged()因为前者是局部刷新,只会刷新item变化的部分,而后者会整体刷新,这样会影响动画效果的显示。

最后再来看看右上角点击事件:

  1. add = (ImageView) findViewById(R.id.add);
  2. add.setOnClickListener(new OnClickListener() {
  3. @Override
  4. public void onClick(View v) {
  5. list.add(1, "大家好,我是新来的,请多多关照");
  6. ivs.add(1, ivs.get((int) (Math.random() * 26)));
  7. myAdapter.notifyItemInserted(1);
  8. }
  9. });

注意刷新方式是一样的。数据添加的位置也是数据显示的位置。

好了,就简单介绍这么多,有问题欢迎留言讨论。

本工程源码下载

版权声明:本文为博主原创文章,未经博主允许不得转载。若有错误地方,还望批评指正,不胜感激。

RecyclerView实现瀑布流效果(图文详解+源码奉送)的更多相关文章

  1. Java开源生鲜电商平台-盈利模式详解(源码可下载)

    Java开源生鲜电商平台-盈利模式详解(源码可下载) 该平台提供一个联合买家与卖家的一个平台.(类似淘宝购物,这里指的是食材的购买.) 平台有以下的盈利模式:(类似的平台有美菜网,食材网等) 1. 订 ...

  2. ArrayList详解-源码分析

    ArrayList详解-源码分析 1. 概述 在平时的开发中,用到最多的集合应该就是ArrayList了,本篇文章将结合源代码来学习ArrayList. ArrayList是基于数组实现的集合列表 支 ...

  3. LinkedList详解-源码分析

    LinkedList详解-源码分析 LinkedList是List接口的第二个具体的实现类,第一个是ArrayList,前面一篇文章已经总结过了,下面我们来结合源码,学习LinkedList. 基于双 ...

  4. [Android Pro] RecyclerView实现瀑布流效果(二)

    referece to : http://blog.csdn.net/u010687392 在上篇中我们知道RecyclerView中默认给我们提供了三种布局管理器,分别是LinearLayoutMa ...

  5. RecyclerView实现瀑布流效果(二)

    在上篇中我们知道RecyclerView中默认给我们提供了三种布局管理器,分别是LinearLayoutManager.GridLayoutManager.StaggeredGridLayoutMan ...

  6. 转载—— android 瀑布流的实现详解,附源码

    介绍 参考自:https://github.com/dodola/android_waterfall,因为原来的代码封装不好,所以,我根据源码的思路,重新写了一遍,所以有了现在这个项目:https:/ ...

  7. Shiro的Filter机制详解---源码分析

    Shiro的Filter机制详解 首先从spring-shiro.xml的filter配置说起,先回答两个问题: 1, 为什么相同url规则,后面定义的会覆盖前面定义的(执行的时候只执行最后一个). ...

  8. udhcp详解源码(序)

    最近负责接入模块,包括dhcp.ipoe和pppoe等等.所以需要对dhcp和ppp这几个app的源代码进行一些分析.网上有比较好的文章,参考并补充自己的分析. 这篇udhcp详解是基于busybox ...

  9. Shiro的Filter机制详解---源码分析(转)

    Shiro的Filter机制详解 首先从spring-shiro.xml的filter配置说起,先回答两个问题: 1, 为什么相同url规则,后面定义的会覆盖前面定义的(执行的时候只执行最后一个). ...

随机推荐

  1. ECshop 在迁移到 PHP7 时遇到的兼容性问题

    在 PHP7 上安装 ECShop V2.7.3时,报错! Deprecated: Methods with the same name as their class will not be cons ...

  2. Desert King

    poj2728:http://poj.org/problem?id=2728 题意:给你n的点,每一个点会有一个坐标(x,y),然后还有一个z值,现在上你求一棵生成树,是的这棵生成树的所有边的费用/所 ...

  3. 使AspNetPager控件中文显示分页信息

    在日常的编程过程中,很多学员对于使AspNetPager控件中文显示分页信息不是很清楚,本文将由达内的老师为各位学员介绍一下使AspNetPager控件中文显示分页信息的内容. AspNetPager ...

  4. 【USACO 2012 Open】Running Laps(树状数组)

    53 奶牛赛跑 约翰有 N 头奶牛,他为这些奶牛准备了一个周长为 C 的环形跑牛场.所有奶牛从起点同时起跑,奶牛在比赛中总是以匀速前进的,第 i 头牛的速度为 Vi.只要有一头奶牛跑完 L 圈之后,比 ...

  5. Android应用架构

    Android开发生态圈的节奏非常之快.每周都会有新的工具诞生,类库的更新,博客的发表以及技术探讨.如果你外出度假一个月,当你回来的时候可能已经发布了新版本的Support Library或者Play ...

  6. C++中new和不new的区别

    我们都知道C++中有三种创建对象的方法,如下: 复制代码代码如下: #include <iostream>using namespace std; class A{private:    ...

  7. perl静态编译DBD

    编译DBD 项目中经常使用perl,但perl在连接数据库时,需要依赖DBI,DBD驱动,但默认安装DBD驱动时,需要依赖数据库的lib库. 比如perl连接MySQL,需要安装MySQL clien ...

  8. bzoj2004

    反正N<=10^9肯定是矩阵乘法反正p<=10肯定是状压dp首先有一个非常重要的性质是任意连续P个站,必须保证K辆车必须停在其中的一个站我们设f[i,S]表示到第i个站搞定了后,这K辆公交 ...

  9. ArcGIS_系列中文教程

    转自:http://www.cnblogs.com/gispeng/archive/2008/04/15/1154212.html  ArcGIS_系列中文教程 如链接有问题请在留言中说明ArcGIS ...

  10. (转载)Linux系统调用及用户编程接口(API)

    (转载)http://www.farsight.com.cn/news/emb167.htm 1 Linux系统调用 所谓系统调用是指操作系统提供给用户程序调用的一组“特殊”接口,用户程序可以通过这组 ...