欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android RecylerView入门教程

程序员文章站 2024-03-04 20:01:18
今年google i/0大会,google开放了两个全新的视图:recyclerview和cardview。这篇文章会提供关于recylerview的简介。 recyle...

今年google i/0大会,google开放了两个全新的视图:recyclerview和cardview。这篇文章会提供关于recylerview的简介。
recylerview作为support-library发布出来,这对开发者来说绝对是个好消息。因为可以在更低的android版本上使用这个新视图。下面我们看如何获取recylerview。首先打开android sdk manager,然后更新extras->android support library即可。

Android RecylerView入门教程

然后在本地../sdk/extras/android/support/v7中找到recyclerview。我已经将下载好的recyclerview整理成一个eclipse可编译的library工程上传到github,有需求的同学请戳。

示例程序

我将通过recylerview制作一个横向滑动的“listview”,下面是示例程序的截图。并在actionbar上设置数据的添加/删除操作。请同学们注意,recyclerview的接口google可能会继续优化和修改,所以最终的版本可能和我提供的程序有出入。demo程序github链接

Android RecylerView入门教程

为什么要使用recyclerview?

google在是这样描述recyclerview的:

"a flexible view for providing a limited window into a large data set."
所以recyclerview适用于无法在一个屏幕范围内展现格式一样的数据时,需要用多行或多列来展示。例如展示联系人,图片,视频等。用户需要滑动屏幕来查看数据,这时recyclerview的特性就有用武之地了。比如,当用户滑动使当前一个可视的item滑出屏幕,这个item的视图将会被回收并在一个新item进入可视范围后重新被使用。

Android RecylerView入门教程

如下图所示,用户滑动向上滑动左边的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相关的非常重要的类列表。

Android RecylerView入门教程

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:
[java] view plain copy
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