最近有时间研究了一下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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:orientation="vertical"
tools:context="com.example.recyclerview_waterfall.MainActivity" > <LinearLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="right"> <ImageView
android:id="@+id/add"
android:layout_width="24dp"
android:layout_margin="12dp"
android:layout_height="24dp"
android:src="@drawable/add" />
</LinearLayout> <android.support.v7.widget.RecyclerView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> </LinearLayout>

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


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:padding="1dp"
android:layout_height="wrap_content" > <ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#B0E0E6"
android:src="@drawable/ic_launcher" /> <TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:textSize="18sp" /> </FrameLayout>

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

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

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

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

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

/**
* 初始化模拟数据
*/
private void initData() {
list = new ArrayList<String>();
ivs = new ArrayList<Integer>();
heights = new ArrayList<Integer>();
for (int i = 'A'; i <= 'Z'; i++) {
list.add("" + (char) i);
heights.add((int) (100 + Math.random() * 300));
}
ivs.add(R.drawable.p1);
ivs.add(R.drawable.p2);
ivs.add(R.drawable.p3);
ivs.add(R.drawable.p4);
ivs.add(R.drawable.p5);
ivs.add(R.drawable.p6);
ivs.add(R.drawable.p7);
ivs.add(R.drawable.p8);
ivs.add(R.drawable.p9);
ivs.add(R.drawable.p10);
ivs.add(R.drawable.p11);
ivs.add(R.drawable.p12);
ivs.add(R.drawable.p13);
ivs.add(R.drawable.p14);
ivs.add(R.drawable.p15);
ivs.add(R.drawable.p16);
ivs.add(R.drawable.p17);
ivs.add(R.drawable.p18);
ivs.add(R.drawable.p19);
ivs.add(R.drawable.p20);
ivs.add(R.drawable.p21);
ivs.add(R.drawable.p22);
ivs.add(R.drawable.p23);
ivs.add(R.drawable.p24);
ivs.add(R.drawable.p25);
ivs.add(R.drawable.p26);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
mScreenWidth = dm.widthPixels;
}

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

list表示TextView上显示的数据

ivs表示ImageView上显示图片的id

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

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

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

public class WaterFallAdapter extends Adapter {

    private Context context;
private List<String> list;
private LayoutInflater layoutInflater;
private List<Integer> heights;
private List<Integer> ivs;
private int mScreenWidth;
public OnItemClickListener listener; public interface OnItemClickListener {
void onItemClick(View v, int position); void onItemLongClick(View v, int position);
} public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.listener = onItemClickListener;
} public WaterFallAdapter(Context context, List<String> list,
List<Integer> heights, List<Integer> ivs, int mScreenWidth) {
this.context = context;
this.list = list;
this.heights = heights;
this.ivs = ivs;
this.mScreenWidth = mScreenWidth;
layoutInflater = LayoutInflater.from(context); } @Override
public int getItemCount() {
return ivs.size();
} @Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
final MyViewHolder vHolder = (MyViewHolder) viewHolder;
LayoutParams tvLp = vHolder.tv.getLayoutParams();
tvLp.height = heights.get(position);
tvLp.width = mScreenWidth / 3;
vHolder.tv.setLayoutParams(tvLp);
vHolder.tv.setText(list.get(position));
vHolder.iv.setLayoutParams(tvLp);
vHolder.iv.setImageResource(ivs.get(position));
vHolder.iv.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
int position2 = vHolder.getPosition();
listener.onItemClick(v, position2);
}
});
vHolder.iv.setOnLongClickListener(new OnLongClickListener() { @Override
public boolean onLongClick(View v) {
int position2 = vHolder.getPosition();
listener.onItemLongClick(v, position2);
return true;
}
});
} @Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int pos) {
View v = layoutInflater.inflate(R.layout.item, null);
ViewHolder vh = new MyViewHolder(v);
return vh;
} public static class MyViewHolder extends RecyclerView.ViewHolder { public TextView tv;
public ImageView iv; public MyViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.tv);
iv = (ImageView) itemView.findViewById(R.id.iv);
} }
}

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

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

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

            myAdapter.setOnItemClickListener(new OnItemClickListener() {

            @Override
public void onItemLongClick(View v, int position) {
Toast.makeText(MainActivity.this, position + "--long click",
Toast.LENGTH_SHORT).show();
list.remove(position);
ivs.remove(position);
myAdapter.notifyItemRemoved(position);
} @Override
public void onItemClick(View v, int position) {
Toast.makeText(MainActivity.this, position + "--click",
Toast.LENGTH_SHORT).show();
}
});

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

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

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

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

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

本工程源码下载

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

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. [原博客] BZOJ 2725 : [Violet 6]故乡的梦

    这个题在bzoj上好像是个权限题,想做的可以去Vani的博客下载测试数据.这里有题面. 简单叙述一下题意:给你一个n个点.m条边的带权无向图,S点和T点,询问Q次删一条给定的边的S-T最短路. 其中  ...

  2. Mysql大表查询优化技巧总结及案例分析

    http://www.169it.com/article/3219955334.html     sql语句使用基本原则:1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 orde ...

  3. 【UVA 10816】 Travel in Desert (最小瓶颈树+最短路)

    [题意] 有n个绿洲, m条道路,每条路上有一个温度,和一个路程长度,从绿洲s到绿洲t,求一条道路的最高温度尽量小, 如果有多条, 选一条总路程最短的. InputInput consists of ...

  4. iOS开发控制器之间传值的几种小方法

    在IOS开发中或面试中,经常会遇到,两个或者多个控制器之间传值的问题 ,总结的集中方法仅供参考! 问题 :将B控制器中的textField 输入内容,传到A控制器中的label上显示出来,如何传值? ...

  5. java 常量池

    在jvm规范中,每个类型都有自己的常量池.常量池是某类型所用常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型.字段.方法的符号引用.之所以是符号引用而不是像c语言那样,编译时直接 ...

  6. dom4j中 selectSingleNode 或selectNodes获取不到节点的原因总结 (转)

    没想到搞个dom4j会出这么多怪错.. 最近在研究XBRL GL的有关内容,在项目中要求吧XBRL GL导入到11179注册库中,根据11179建立数据库,然后从XBRL GL分类标准中导入数据到数据 ...

  7. 从零开始学习ASP.NET MVC 1.0

    转自:http://www.cnblogs.com/zhangziqiu/archive/2009/02/27/ASPNET-MVC-1.html <从零开始学习ASP.NET MVC 1.0& ...

  8. 初次运行 Git 前的配置

    初次运行 Git 前的配置 一般在新的系统上,我们都需要先配置下自己的 Git 工作环境.配置工作只需一次,以后升级时还会沿用现在的配置.当然,如果需要,你随时可以用相同的命令修改已有的配置. Git ...

  9. NIO的学习

    参考 http://wenku.baidu.com/link?url=rq-BEp3Et4JRrE62f2Lv9hq8nT_Gq0XPb65h8OBqTAt-ILfqKmdjIhVEp8bctIdm0 ...

  10. 进程与线程(四) linux进程间通信的方式总结

    1概述: 上文说到,每个进程都有自己的地址空间,包括什么呢?向下生长得栈,向上生长的堆,代码段,数据段等,这些都是进程私有的,如何实现通信的呢?通信需要媒介,这个媒介很重要. 对于研发人员来说,进程不 ...