recyclerview用法,recyclerview是什么,RecyclerView使用详解

recyclerview用法,recyclerview是什么,RecyclerView使用详解

本文主要对回收视图的使用进行了详细介绍,文章结尾附上源码下载,具有一定的参考价值,下面跟着小编一起来看下吧

RecylerView介绍

再循环视图是支持-v7包中的新组件,是一个强大的滑动组件,与经典的列表视图相比,同样拥有项目回收复用的功能,这一点从它的名字再循环视图即回收视角也可以看出。官方对于它的介绍则是:回收视图是列表视图的升级版本,更加先进和灵活回收视图通过设置布局管理器、项目装饰、项目动画制作人实现你想要的效果。

使用布局管理器来确定每一个项目的排列方式。

使用项目装饰自己绘制分割线,更灵活

使用ItemAnimator为增加或删除一行设置动画效果。

注意

新建完项目,需要在app/build.gradle增加再循环视图依赖,不然找不到回收视图类

编译“通讯器。安卓。支持:回收器视图-V7:23。1 .0"

RecylerView简单的Demo

我们来看活动代码,跟列表视图写法差不多,只是这边多设置了布局管理器。

公共类LinearLayoutActivity扩展了AppCompatActivity {

私有回收视图回收视图

私有RecyclerViewAdapter适配器;

私有列表字符串数据;

@覆盖

创建时的公共void(绑定保存的实例状态){

超级棒。oncreate(savedInstanceState);

setContentView(r . layout。recycler _ main);

initData();

回收视图=(回收视图)findViewById(r . id。回收视图);

回收视图。setlayoutmanager(new LinearLayoutManager(this));//设置布局管理器

回收器视图。additem装饰(新的分隔项目装饰(this));

recyclerview。set adapter(adapter=new recyclervieadapter(this,datas));

}

私有void initData(){

datas=new ArrayList();

for(int I=0;i100i ){

数据。add(' item:' I ');

}

}

}

活动对应的布局文件:recycler_main.xml

?可扩展标记语言版本='1.0 '编码='utf-8 '?

相对布局xmlns:Android=' http://模式。安卓。' com/apk/RES/Android '

Android:layout _ width=' match _ parent '

Android:layout _ height=' match _ parent '

安卓。支持。V7。小部件。回收视图

Android:id=' @ id/recycle view '

Android:layout _ width=' match _ parent '

Android:layout _ height=' match _ parent '/

/RelativeLayout

适配器相对列表视图来说变化比较大的。把取景器逻辑封装起来了,代码相对简单一些。

需要继承回收查看.适配器,重写三个方法

MyViewHolder需要继承回收查看.取景器

公共类RecyclerViewAdapter扩展了回收查看.adapterrecyclerviedapter。我的视图持有者{

私有列表字符串数据;

私人布局充气机;

公共RecyclerViewAdapter(上下文上下文,列表字符串数据){

inflater=LayoutInflater.from(上下文);

this.datas=datas

}

//创建每一行的视角用回收查看.取景器包装

@覆盖

公共回收适配器MyViewHolder oncreateviewmolder(视图组parent,int viewType) {

查看项目视图=充气机。膨胀(r .布局。recycler _ item,null);

返回新的myview holder(项目视图);

}

//给每一行视角填充数据

@覆盖

公共void onBindViewHolder(recyclervieadapter .MyViewHolder holder,int位置){

持有人。文本视图。settext(数据。get(位置));

}

//数据源的数量

@覆盖

public int getItemCount() {

返回数据。size();

}

MyViewHolder类扩展回收查看.取景框{

私有文本视图文本视图

公共我的视图持有者(查看项目视图){

超级(项目视图);

TextView=(TextView)项目视图。findviewbyid(r . id。TextView);

}

}

}

我们来看看效果图:

RecyclerView增加分隔线

回收视图是没有安卓:分割线跟android:dividerHeight属性的,如果我们需要分割线,就只能自己动手去实现了。

需要继承项目装饰类,实现翁德劳跟getItemOffsets方法。

调用回收视图的附加装饰方法。

我们先写一个装饰类,继承回收查看.项目装饰,在getItemOffsets留出项目之间的间隔,然后就会调用翁德劳方法绘制(翁德劳的绘制优先于每一行的绘制)

公共类分隔符项目装饰扩展回收查看.项目装饰{

/*

*回收视图的布局方向,默认先赋值为纵向布局

*回收视图布局可横向,也可纵向

* 横向和纵向对应的分割线画法不一样

* */

private int memory=LinearLayoutManager .垂直;

private int mite msize=1;//项目之间分割线的尺寸,默认为一

私漆mPaint//绘制项目分割线的画笔,和设置其属性

公共分隔项目装饰(上下文上下文){

这(上下文,LinearLayoutManager .垂直,r .颜色颜色强调);

}

公共分隔符项装饰(上下文Context,int orientation) {

这(上下文、方向、r .颜色。颜色强调);

}

公共分隔符项装饰(Context Context,int orientation,int dividerColor){

this(context,orientation,dividerColor,1);

}

/**

* @param上下文

* @param方向绘制方向

* @param dividerColor分割线颜色颜色资源身份证明(识别)

* @param mItemSize分割线宽度传入数据处理值就行

*/

公共分隔符项装饰(Context Context,int orientation,int dividerColor,int mitesize){

this.mOrientation=方位

如果(定向!=LinearLayoutManager .垂直方向!=LinearLayoutManager .水平){

抛出新的IllegalArgumentException('请传入正确的参数') ;

}

//把数据处理值换算成像素

这个。mitesize=(int)类型值。应用维度(键入得值.COMPLEX_UNIT_DIP,mItemSize,context.getResources().getDisplayMetrics());

mPaint=新油漆(油漆ANTI _ ALIAS _ FLAG);

MP int。设置颜色(上下文。获取资源().getColor(分割线颜色));

}

@覆盖

公共void onDraw(Canvas c,RecyclerView parent,RecyclerView .State state) {

if(mori entation==LinearLayoutManager .垂直){

drawVertical(c,parent);

}否则{

drawHorizontal(c,parent);

}

}

/**

* 绘制纵向项目分割线

* @param画布

* @param parent

*/

私有void垂直绘制(Canvas Canvas,RecyclerView parent){

final int left=parent。get padding left();

final int right=parent。getmeasuredwidth()-parent。get padding right();

final int childSize=parent。获取子计数();

for(int I=0;我儿童尺寸;i ){

最终视图子视图=父视图。在(I)处获得孩子;

回收查看.layout params layout params=(回收视图.布局参数)子项。get layout params();

final int top=child。getbottom()布局参数。底部边距;

final int bottom=top mItemSize

canvas.drawRect(左、上、右、下、mPaint);

}

}

/**

* 绘制横向项目分割线

* @param画布

* @param parent

*/

私有水平绘制无效(画布Canvas,RecyclerView parent){

final int top=parent。get padding top();

最终int bottom=parent。getmeasuredheight()-parent。getpaddingbottom();

final int childSize=parent。获取子计数();

for(int I=0;我儿童尺寸;i ){

最终视图子视图=父视图。在(I)处获得孩子;

回收查看.layout params layout params=(回收视图.布局参数)子项。get layout params();

final int left=child。getright()布局参数。右边距;

final int right=left mItemSize

canvas.drawRect(左、上、右、下、mPaint);

}

}

/**

* 设置项目分割线的大小

* @param outRect

* @param视图

* @param parent

* @param状态

*/

@覆盖

公共void getitem偏移量(Rect outRect,View view,RecyclerView parent,RecyclerView .State state) {

if(mori entation==LinearLayoutManager .垂直){

outRect.set(0,0,0,mite msize);//垂直排列底部偏移

}否则{

outRect.set(0,0,mItemSize,0);//水平排列右边偏移

}

}

}

不要忘记调用附加装饰方法哦

回收器视图。additem装饰(新的分隔项目装饰(this));//添加分割线

重新运行,效果图:

大家读到这里肯定会有一个疑问,这货比列表视图麻烦多了啊,但是谷歌官方为什么要说是列表视图的升级版呢?接下来开始放大招。

GridLayoutManager

在回收视图中实现不同的列表,只需要切换不同的布局管理器即可回收查看.布局管理器跟回收查看.项目装饰一样,都是回收视图静态抽象内部类,但是布局管理器有三个官方写好的实现类。

LinearLayoutManager线性布局管理器跟列表视图功能相似

GridLayoutManager网格布局管理器跟显示数据表格(一种控件)功能相似

StaggeredGridLayoutManager瀑布流布局管理器

刚刚我们用的是LinearLayoutManager,现在我们切换到GridLayoutManager,看到下面这句代码,有没有感觉分分钟切换不同列表显示。

回收视图。setlayoutmanager(new GridLayoutManager(this,2));

如果要显示多列或者要纵向显示就新的不同的构造方法,以下代码纵向显示四列。当前如果你还需要反方向显示,把错误的改成真实的就可以。

回收视图。setlayoutmanager(new GridLayoutManager(this,4,GridLayoutManager .横,假));

因为用的是网格布局,所以呢绘制分割线的代码需要重新修改一下。网格布局一行可以有多列,并且最后一列跟最后一行不需要绘制,所以我们得重新创建一个类。

DividerGridItemDecoration.java

公共类划分网格划分扩展回收查看.项目装饰{

/*

*回收视图的布局方向,默认先赋值为纵向布局

*回收视图布局可横向,也可纵向

* 横向和纵向对应的分割线画法不一样

* */

private int memory=LinearLayoutManager .垂直;

private int mite msize=1;//项目之间分割线的尺寸,默认为一

私漆mPaint//绘制项目分割线的画笔,和设置其属性

公共除数上下文上下文){

这(上下文,LinearLayoutManager .垂直,r .颜色颜色强调);

}

公共分隔符griditemdecoration(上下文Context,int orientation) {

这(上下文、方向、r .颜色。颜色强调);

}

public DividerGridItemDecoration(Context Context,int orientation,int dividerColor){

this(context,orientation,dividerColor,1);

}

/**

* @param上下文

* @param方向绘制方向

* @param dividerColor分割线颜色颜色资源身份证明(识别)

* @param mItemSize分割线宽度传入数据处理值就行

*/

public DividerGridItemDecoration(Context Context,int orientation,int dividerColor,int mItemSize){

this.mOrientation=方位

如果(定向!=LinearLayoutManager .垂直方向!=LinearLayoutManager .水平){

抛出新的IllegalArgumentException('请传入正确的参数') ;

}

//把数据处理值换算成像素

这个。mitesize=(int)类型值。应用维度(键入得值.COMPLEX_UNIT_DIP,mItemSize,context.getResources().getDisplayMetrics());

mPaint=新油漆(油漆ANTI _ ALIAS _ FLAG);

MP int。设置颜色(上下文。获取资源().getColor(分割线颜色));

}

@覆盖

公共void onDraw(Canvas c,RecyclerView parent,RecyclerView .State state) {

drawHorizontal(c,parent);

drawVertical(c,parent);

}

private int getSpanCount(回收视图父级){

//列数

int span计数=-1;

回收查看.布局管理器布局管理器=父级。getlayoutmanager();

GridLayoutManager的布局管理器实例){

span count=((GridLayoutManager)布局管理器).getSpanCount();

} else if(StaggeredGridLayoutManager的布局管理器实例){

span count=((StaggeredGridLayoutManager)布局管理器).getSpanCount();

}

返回跨距计数;

}

公共水平绘制无效(画布Canvas,RecyclerView parent) {

int子计数=父计数。获取子计数();

for(int I=0;我数孩子;i ) {

最终视图子视图=父视图。在(I)处获得孩子;

最终回收视图布局参数params=(循环视图.布局参数)子项。get layout params();

final int left=child。get left()-params。左边距;

final int right=child。getright()参数。右边界螨虫;

final int top=child。getbottom()参数。底部边距;

final int bottom=top mItemSize

canvas.drawRect(左、上、右、下、mPaint);

}

}

公共void drawVertical(Canvas canvas,RecyclerView parent) {

最终int子计数=父计数。获取子计数();

for(int I=0;我数孩子;i ) {

最终视图子视图=父视图。在(I)处获得孩子;

最终回收视图布局参数params=(循环视图.布局参数)子项。get layout params();

final int top=child。gettop()-params。上边距;

final int bottom=child。getbottom()参数。底部边距;

final int left=child。getright()参数。右边距;

final int right=left mItemSize

canvas.drawRect(左、上、右、下、mPaint);

}

}

@覆盖

公共void getitem偏移量(Rect outRect,int itemPosition,RecyclerView parent) {

int spanCount=getSpanCount(parent);

int子计数=父计数。获取适配器().getItemCount();

if(is lasrow(parent,itemPosition,spanCount,childCount)){//如果是最后一行,不需要绘制底部

outRect.set(0,0,mItemSize,0);

} else if (isLastColum(parent,itemPosition,spanCount,childCount)){//如果是最后一列,不需要绘制右边

outRect.set(0,0,0,mite msize);

}否则{

outRect.set(0,0,mItemSize,mite msize);

}

}

private boolean isLastColum(循环视图父级,int pos,int spanCount,int childCount) {

回收查看.布局管理器布局管理器=父级。getlayoutmanager();

GridLayoutManager的布局管理器实例){

如果(位置1) % spanCount==0){//如果是最后一列,则不需要绘制右边

返回真实的

}

} else if(StaggeredGridLayoutManager的布局管理器实例){

int orientation=((StaggeredGridLayoutManager)布局管理器).get orientation();

if(orientation==StaggeredGridLayoutManager .垂直){

如果(位置1) % spanCount==0){//如果是最后一列,则不需要绘制右边

返回真实的

}

}否则{

子计数=子计数-子计数% span计数;

if (pos=childCount)//如果是最后一列,则不需要绘制右边

返回真实的

}

}

返回错误的

}

private boolean是straw(recycle view parent,int pos,int spanCount,int childCount) {

回收查看.布局管理器布局管理器=父级。getlayoutmanager();

GridLayoutManager的布局管理器实例){

子计数=子计数-子计数% span计数;

if (pos=childCount)//最后一行

返回真实的

} else if(StaggeredGridLayoutManager的布局管理器实例){

int orientation=((StaggeredGridLayoutManager)布局管理器).get orientation();

if(orientation==StaggeredGridLayoutManager .垂直){//纵向

子计数=子计数-子计数% span计数;

if (pos=childCount)//最后一行

返回真实的

} else{ //横向

如果(位置1) % spanCount==0) {//是最后一行

返回真实的

}

}

}

返回错误的

}

}

写了这两个画分割线的类,主流的布局:线性列表跟网格列表都能展示了。赶紧运行代码看看结果:

StaggeredGridLayoutManager

活动性中修改下布局管理器,大家应该感觉很熟悉了吧~~~

recyclerView.setLayoutManager(新StaggeredGridLayoutManager(3,StaggeredGridLayoutManager .垂直));

瀑布流列表一般列的高度是不一致的,为了模拟不同的宽高,数据源我把线类型改成了对象。然后初始化的时候随机了一个高度。

公共类项目数据{

私有字符串内容;//项目内容

私有int高度;//项目高度

公共项目数据(){

}

公共项目数据(字符串内容,整数高度){

this.content=内容;

this.height=高度;

}

公共字符串getContent() {

返回内容;

}

公共void setContent(字符串内容){

this.content=内容;

}

public int getHeight() {

返回高度;

}

公共空设置高度(int height){

this.height=高度;

}

}

瀑布流列表没有添加分割线,给项目布局设置了安卓:填充属性。recycler_staggered_item.xml

?可扩展标记语言版本='1.0 '编码='utf-8 '?

框架布局xmlns:Android=' http://模式。安卓。' com/apk/RES/Android '

android:padding='5dp '

Android:layout _ width=' wrap _ content '

Android:layout _ height=' match _ parent '

文本视图

android:id='@ id/textview '

Android:background=' @ color/color accent '

android:layout_width='100dp '

Android:layout _ height=' wrap _ content '

安卓:重力='中心'

android:text='122 '

android:textSize='20sp'/

/框架布局

最后我们在适配器的onBindViewHolder方法中给项目d中的文本视图设置一个高度

@覆盖

public void onBindViewHolder(StaggeredGridAdapter .MyViewHolder holder,int位置){

项目数据项目数据=数据。get(位置);

持有人。文本视图。settext(项目数据。get content());

//手动更改高度,不同位置的高度有所不同

持有人。文本视图。设置高度(项目数据。get height());

}

是不是感觉如此简单,赶紧运行看看效果:

添加header跟footer

回收视图添加头部跟底部是没有对应的美国石油学会(美国石油协会)的,但是我们很多的需求都会用到,于是只能自己想办法实现了。我们可以通过适配器的getItemViewType方法来实现这个功能。

修改后的适配器代码:recyclerheadfootviewadapter。Java 语言(一种计算机语言,尤用于创建网站)

公共类RecyclerHeadFootViewAdapter扩展了回收查看.AdapterRecyclerView。取景框{

私有列表字符串数据;

私人布局充气机;

public static final int TYPE _ HEADER=1;//标头类型

public static final int TYPE _ FOOTER=2;//页脚类型

私有视图头=null//头视角

私有视图页脚=null//脚视角

公共RecyclerHeadFootViewAdapter(上下文上下文,列表字符串数据){

inflater=LayoutInflater.from(上下文);

this.datas=datas

}

//创建每一行的视角用回收查看.取景器包装

@覆盖

公共回收视图视图持有者oncreateview holder(视图组parent,int viewType) {

if(viewType==TYPE_HEADER){

返回新的回收查看.视图持有人(表头){ };

} else if(view TYPE==TYPE _ FOOTER){

返回新的回收查看.取景框(页脚){ };

}

查看项目视图=充气机。膨胀(r .布局。recycler _ item,null);

返回新的myview holder(项目视图);

}

//给每一行视角填充数据

@覆盖

公共void onBindViewHolder(回收器视图.取景器支架,中间位置){

if(getItemViewType(position)==TYPE _ HEADER | | getItemViewType(position)==TYPE _ FOOTER){

返回;

}

我的观点持有人my holder=(我的观点持有人)holder;

我的固定器。文本视图。settext(数据。get(获取真实位置(位置)));

}

//如果有头部位置的位置是从一开始的所以需要-1

public int getRealPosition(int position){

返回头==null?位置:位置-1;

}

//数据源的数量

@覆盖

public int getItemCount() {

if(header==null footer==null){//没有头跟脚

返回数据。size();

}else if(表头==空表尾!=null){//head为空脚不为空

返回数据。size()1;

}else if(表头!=空页脚==null){//页眉不为空脚为空

返回数据。size()1;

}否则{

返回数据。size()2;//头不为空脚不为空

}

}

@覆盖

public int getItemViewType(int position){

//如果头布局不为空位置是第一个那就是头类型

如果(表头!=nullposition==0){

返回类型_标题

}else if(页脚!=null position==getItemCount()-1){//如果页脚不为空最后一个

返回类型_页脚

}

返回超级棒。getitemviewtype(位置);

}

公共void setHeader(查看标题){

this.header=header

notifyItemInserted(0);//在位置0插入一条数据,然后刷新

}

公共void设置页脚(视图页脚){

this.footer=页脚;

notifyItemInserted(数据。size()-1);//在尾部插入一条数据,然后刷新

}

MyViewHolder类扩展回收查看.取景框{

私有文本视图文本视图

公共我的视图持有者(查看项目视图){

超级(项目视图);

TextView=(TextView)项目视图。findviewbyid(r . id。TextView);

}

}

}

getItemCount

有页眉跟页脚的时候需要在源数据长度基础上进行增加。

getItemViewType

通过getItemViewType判断不同的类型

onCreateViewHolder

通过不同的类型创建项目的视角

onBindViewHolder

如果是页眉跟页脚类型是不需要绑定数据的,标题跟页脚的视角一般在活动性中创建,不需要这边做处理,所以这两种类型我们就不往下执行,如果有头布局,位置==0的位置被页眉占用了,但是我们的数据源也就是集合的下标是从0开始的,所以这里需要-1。

setHeader

设置头布局,在第一行插入一条数据,然后刷新。注意这个方法调用后会有插入的动画,这个动画可以使用默认的,也可以自己定义

设置页脚

设置尾部布局,在尾部插入一条数据,然后刷新。

添加页眉跟页脚的方法终于封装好了,在活动中只需要两行代码就能添加标题,跟列表视图调用添加标题方法一样简单,又可以幸福的的玩耍了。这里需要注意的是我们初始化视角的时候,膨胀方法需要三个参数。

资源资源身份证明(识别)

根父视角

attachToRoot true:返回父查看错误:返回资源身份证明(识别)生成的视角

//添加页眉

view header=layoutinflater。从(这)开始.膨胀(r .布局。recycler _ header,recyclerView,false);

适配器。设置表头(表头);

//添加页脚

视图页脚=布局页脚。从(这)开始.膨胀(r .布局。recycler _ footer,recyclerView,false);

adapter.setFooter(页脚);

回收器_表头跟回收器_页脚布局文件我就不贴出来了,就一个文本视图,我们直接看效果图:

item点击事件增加或删除带动画效果

当我们调用回收视图的setOnItemClickListener方法的时候,发现居然没有,用了回收视图你要习惯什么东西都自己封装。

首先我们从适配器开刀,内部写一个接口,一个实例变量,提供一个公共方法,设置监听。

私有RecyclerViewItemClick RecyclerViewItemClick;

public void setRecyclerViewItemClick(RecyclerViewItemClick RecyclerViewItemClick){

这个。recyclerViewItemClick=recyclerViewItemClick;

}

公共接口RecyclerViewItemClick{

/**

*项目点击

* @param实数位置数据源位置

* @param位置视图位置

*/

void onItemClick(int实数位置,int位置);

}

在onBindViewHolder方法中给项目监听点击事件

if(recyclerViewItemClick!=null) {

我的固定器。项目视图。setonclicklistener(新视图OnClickListener() {

@覆盖

公共void onClick(视图五){

recyclerviewitemclick。onitemclick(getRealPosition(position),position);

}

});

}

在活动的onCreate方法中进行监听,顺便设置项目增加删除动画。我用的是软件开发工具包自带的默认动画。

适配器。setrecyclerviewitemclick(recyclerViewItemClick);

回收视图。setitem animator(new default item animator());

私有RecyclerHeadFootViewAdapter .RecyclerViewItemClick RecyclerViewItemClick=new RecyclerHeadFootViewAdapter .RecyclerViewItemClick() {

@覆盖

public void onItemClick(int real position,int position) {

Log.i('安森','删除数据:"真实位置"视图位置:'位置);

Log.i('安森','当前位置:"位置"更新项目数量:'(适配器。getitemcount()-position-1));

数据。移除(真实位置);//删除数据源

adapter.notifyItemRemoved(位置);//项目移除动画

//更新位置至adapter.getItemCount()-1的数据

适配器。notifyitemrangechanged(位置,适配器。getitemcount()-position-1);

}

};

源码下载

回收视图

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: