【Android 界面效果47】RecyclerView详解
RecylerView作为 support-library发布出来,这对开发者来说绝对是个好消息。因为可以在更低的Android版本上使用这个新视图。下面我们看如何获取 RecylerView。首先打开Android SDK Manager,然后更新Extras->Android Support Library即可。
然后在本地../sdk/extras/android/support/v7中找到recyclerview。我已经将下载好的Recyclerview整理成一个Eclipse可编译的Library工程上传到Github,有需求的同学请戳链接。
示例程序
我将通过
RecylerView制作一个横向滑动的“ListView”,下面是示例程序的截图。并在ActionBar上设置数据的添加/删除操作。请同学们注
意,RecyclerView的接口Google可能会继续优化和修改,所以最终的版本可能和我提供的程序有出入。Demo程序Github链接。
为什么要使用RecyclerView?
Google在是这样描述RecyclerView的:
"A flexible view for providing a limited window into a large data set."
所
以RecyclerView适用于无法在一个屏幕范围内展现格式一样的数据时,需要用多行或多列来展示。例如展示联系人,图片,视频等。用户需要滑动屏幕
来查看数据,这时RecyclerView的特性就有用武之地了。比如,当用户滑动使当前一个可视的Item滑出屏幕,这个Item的视图将会被回收并在
一个新Item进入可视范围后重新被使用。
如下图所示,用户滑动向上滑动左边的RecyclerView,No.0和No.1就会滑出屏幕可视范围,这时右图的No.0和No.1的视图将会被RecyclerView放入一个可重复利用的缓存中以备再次使用。
可回收利用View是个很实用的功能,它不仅可以减少CPU不断inflate View的开销,而且可以节省缓存View的内存开销。
这
时,你可能会问:这不是一个新功能啊!是的,我们已经在使用ListView的时候使用了这个机制,但是当使用ListView时,显示,回收等功能是紧
密耦合在一起的,Google现在发布RecyclerView,使方法更灵活,开发者也能自定义各种各样的显示效果。
RecyclerView不再负责显示工作
和ListView不一样的是,RecyclerView不再负责Item的摆放等显示方面的功能。所有和布局、绘制等方面的工作Google都其拆分成不同的类进行管理。所以开发者可以自定义各种各样满足定制需求的的功能类。
下面是一些和RecyclerView相关的非常重要的类列表。
| 类名 | 说明 |
| RecyclerView.Adapter | 托管数据集合,为每个Item创建视图 |
| RecyclerView.ViewHolder | 承载Item视图的子视图 |
| RecyclerView.LayoutManager | 负责Item视图的布局 |
| RecyclerView.ItemDecoration | 为每个Item视图添加子视图,在Demo中被用来绘制Divider |
| RecyclerView.ItemAnimator | 负责添加、删除数据时的动画效果 |
ViewHolder
关于ViewHolder,Google早就推荐开发者使用,但也只是建议。但是现在,RecyclerView.Adapter最终要求开发者必须使用ViewHolder。如果你还对ViewHolder不了解,请阅读Android
training session。
Demo通过继承RecyclerView.ViewHolder来实现自定义:
public class MyViewHolder extends ViewHolder implements OnClickListener,OnLongClickListener{
public ImageView iv;
public TextView tv;
private MyItemClickListener mListener;
private MyItemLongClickListener mLongClickListener;
public MyViewHolder(View rootView,MyItemClickListener listener,MyItemLongClickListener longClickListener) {
super(rootView);
iv = (ImageView)rootView.findViewById(R.id.item_iv);
tv = (TextView)rootView.findViewById(R.id.item_tv);
this.mListener = listener;
this.mLongClickListener = longClickListener;
rootView.setOnClickListener(this);
rootView.setOnLongClickListener(this);
}
/**
* 点击监听
*/
@Override
public void onClick(View v) {
if(mListener != null){
mListener.onItemClick(v,getPosition());
}
}
/**
* 长按监听
*/
@Override
public boolean onLongClick(View arg0) {
if(mLongClickListener != null){
mLongClickListener.onItemLongClick(arg0, getPosition());
}
return true;
}
}
RecyclerView.Adapter
Adapter负责扮演两个角色:不仅为底部数据提供支持而且还负责为数据创建合适的视图。Adapter适用在Android很多控件,例如ListView、AutoCompleteTextView等。
继承RecyclerView.Adapter需要实现以下三个方法:
- public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType)
- public void onBindViewHolder(ViewHolder holder,int position)
- public int getItemCount()
Demo中的Adapter:
public class MyAdapter extends Adapter<MyViewHolder> { private List<MyItemBean> mData;
private MyItemClickListener mItemClickListener;
private MyItemLongClickListener mItemLongClickListener; public MyAdapter(List<MyItemBean> data){
this.mData = data;
} @Override
public int getItemCount() {
return mData.size();
} @Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyItemBean bean = mData.get(position);
holder.tv.setText(bean.tv);
} @Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent,false);
MyViewHolder vh = new MyViewHolder(itemView,mItemClickListener,mItemLongClickListener);
return vh;
}
}
onCreateViewHolder中负责为Item创建视图,onBindViewHolder负责将数据绑定到Item的视图上。
RecyclerView.LayoutManager
LayoutManager是
RecyclerView中最有意思的类。该类负责将每个Item视图在RecylerView中的布局。目前Google提供了
LayoutManager的一个子类:LinearLayoutManager。LinearLayoutManager提供了横向和竖向两种布
局,Demo就是使用LinearLayoutManger的横向布局实现的。
如果要自定义LayoutManager,需要实现一个abstract方法
- public LayoutParams generateDefaultLayoutParams()
Demo中为RecylerView添加LinearLayoutManager的片段:
MyLayoutManager manager = new MyLayoutManager(this);
manager.setOrientation(LinearLayout.HORIZONTAL);//默认是LinearLayout.VERTICAL
mRecyclerView.setLayoutManager(manager);LinearLayoutManager提供了如下几个方法来帮助开发者获取屏幕上的顶部item和底部item:
- findFirstVisibleItemPosition()
- findFirstCompletelyVisibleItemPosition()
- findLastVisibleItemPosition()
- findLastCompletelyVisibleItemPosition()
RecyclerView.ItemDecoration
通过
ItemDecoration可以使各个Item在视觉上相互分开,其实和ListView的Divider很像。ItemDecoration并不是
RecyclerView必须设置的,开发者可以不设置或者设置多个Decoration。RecyclerView会遍历所有的
ItemDecoration并调用各自的绘图方法。继承ItemDecoration需要实现以下三个方法:
- public void onDraw(Canvas c,RecyclerView parent,RecyclerView.State state)
- public void getItemOffset(Rect outRect,int itemPosition,RecyclerView parent)
LayoutManager会调用getItemOffset方法来计算每个Item的Decoration合适的尺寸。
Demo中自定义了一个ItemDecoration来实现ListView的Divider效果:
public class MyDecoration extends ItemDecoration { private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
}; private Drawable mDivider; public MyDecoration(Context ctx){
final TypedArray a = ctx.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
} @Override
public void onDraw(Canvas c, RecyclerView parent, State state) {
int top = parent.getPaddingTop();
int bottom = parent.getHeight() - parent.getPaddingBottom();
int childCount = parent.getChildCount();
for(int i=0;i < childCount;i++){
View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams)child.getLayoutParams();
int left = child.getRight() + layoutParams.rightMargin;
int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
} @Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
State state) {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
} }
RecyclerView.ItemAnimatior
当Item有以下三种操作时ItemAnimatior会为RecyclerView提供动画效果:
- 删除某一个Item
- 添加一个新的Item
- 移动某个Item
Google提供了一个名为DefaultItemAnimator的默认ItemAnimator供开发者使用。如果开发者不为RecyclerView设置ItemAnimator,RecyclerView也会使用默认的DefaultItemAnimator。
显 然,为了让动画效果起效,开发者必须通知Adapter数据有改变。之前我们使用Adapter时会调用notifyDataSetChanged()来 通知Adapter数据改变并更新视图,现在RecyclerView,Adapter提供了许多notifyXyz()方法,例如Demo中使用了以下 两个方法:
- public final void notifyItemInserted(int position)
- public final void notifyItemRemoved(int position)
使用RecyclerView
首先,我们先看如何在xml中使用RecyclerView
<RelativeLayout 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"
tools:context="com.xmy.recylerviewdemo.MainActivity" > <android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/> </RelativeLayout>
然后需要开发者在代码中实现RecyclerView的组装,大体可概括为以下步骤:
- 实例化RecyclerView
- 为RecyclerView设置LayoutManager
- 为RecyclerView设置Adapater
- 如果有需求,可以设置一个或多个ItemDecorations,当然,也可以不设置
- 如果有需求,可以设置ItemAnimator
以上就是对RecyclerView的基本介绍,下篇博客会讲RecyclerView如何像ListView一样为Item设置交互监听。
参考资料:
A First Glance at Android’s RecyclerView
原文:http://blog.csdn.net/guxiao1201/article/details/40399777
【Android 界面效果47】RecyclerView详解的更多相关文章
- Android Design Support Library使用详解
Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的And ...
- Android中Canvas绘图基础详解(附源码下载) (转)
Android中Canvas绘图基础详解(附源码下载) 原文链接 http://blog.csdn.net/iispring/article/details/49770651 AndroidCa ...
- 《Android群英传》读书笔记 (5) 第十一章 搭建云端服务器 + 第十二章 Android 5.X新特性详解 + 第十三章 Android实例提高
第十一章 搭建云端服务器 该章主要介绍了移动后端服务的概念以及Bmob的使用,比较简单,所以略过不总结. 第十三章 Android实例提高 该章主要介绍了拼图游戏和2048的小项目实例,主要是代码,所 ...
- Android中的windowSoftInputMode属性详解
这篇文章主要介绍了Android中的windowSoftInputMode属性详解,本文对windowSoftInputMode的9个属性做了详细总结,需要的朋友可以参考下 在前面的一篇文章中 ...
- 【Android 应用开发】Ubuntu 下 Android Studio 开发工具使用详解 (旧版本 | 仅作参考)
. 基本上可以导入项目开始使用了 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21035637 ...
- 【Android 应用开发】Ubuntu 下 Android Studio 开发工具使用详解
. 基本上可以导入项目开始使用了 ... . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21035637 ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Android 之窗口小部件详解--App Widget
Android 之窗口小部件详解--App Widget 版本号 说明 作者 日期 1.0 添加App Widge介绍和示例 Sky Wang 2013/06/27 1 App ...
- Android不规则点击区域详解
Android不规则点击区域详解 摘要 今天要和大家分享的是Android不规则点击区域,准确说是在视觉上不规则的图像点击响应区域分发. 其实这个问题比较简单,对于很多人来说根本不值得做为一篇博文写出 ...
随机推荐
- J.U.C-其他组件
J.U.C-其他组件 FutureTask 介绍Callable时我们知道它可以有返回值,返回值通过Future进行封装.FutrueTask实现了RunnableFuture接口,该接口继承了R ...
- 使用between and 作为查询条件
- POJ1058 The Gourmet Club
题目来源:http://poj.org/problem?id=1058 题目大意:ACM城的美食俱乐部有16位成员.他们连续了当地的法国餐厅Chatrau Java来安排连续5天的晚餐.晚餐时他们每4 ...
- GIL 线程池 进程池 同步 异步 阻塞 非阻塞
1.GIL 是一个全局解释器锁,是一种互斥锁 为什么需要GIL锁:因为一个python.exe进程中只有一份解释器,如果这个进程开启了多个线程都要执行代码 多线程之间要竞争解释器,一旦竞争就有可能出现 ...
- xlrd和xlwd模块
xlrd模块 是python中一个第三方的用于读取excle表格的模块 exlce结构分析 一个excle表格包含多个sheet 一个sheet中包含多行多列 每个单元格具备唯一的行号和列号 常用函数 ...
- ZPL打印机命令解释
个人备忘: 1.装驱动,装驱动要装对应的ZPL或者EPL版本,目前发现GK888T无需选择,直接装GK888T即可,其他机型未知. 2.标签设计,文本部分用SimSun-ExtB字体,变量内容部分用Z ...
- windows查看网络常用cmd命令
一.ping 主要是测试本机TCP/IP协议配置正确性与当前网络现状. ping命令的基本使用格式是: ping IP地址/主机名/域名 [-t] [-a] [-n count] [-l size] ...
- 用sphinx-doc优雅的写文档
Sphinx 是一个工具,它使得创建一个智能而美丽的文档变得简单.作者Georg Brandl,基于BSD许可证. 起初为写 Python 文档而诞生的 Sphinx,支持为各种语言生成软件开发文档. ...
- linux 文件 s 权限
s权限的作用:表示对文件具用可执行权限的用户将使用文件拥有者的权限或文件拥有者所在组的权限在对文件进行执行. s权限的设置:4,用户拥有者的执行权限位, 6,用户组的执行权限位, 2, 两者都设置, ...
- java——int、args[]传参、标签、数字塔?、一个输入格式
1.当int型整数超出自己范围时,会从它的上界重新开始. public class exp { public static void main(String[] args) { int i = 214 ...