当前位置: 移动技术网 > IT编程>移动开发>Android > Android RecyclerView艺术般的控件使用完全解析

Android RecyclerView艺术般的控件使用完全解析

2019年07月24日  | 移动技术网IT编程  | 我要评论

爱宠有情人,厦门顺丰快递,黑暗之尘

recyclerview出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用。
据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:listview、gridview。

那么有了listview、gridview为什么还需要recyclerview这样的控件呢?整体上看recyclerview架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同layoutmanager,itemdecoration , itemanimator实现令人瞠目的效果。

你想要控制其显示的方式,请通过布局管理器layoutmanager你想要控制item间的间隔(可绘制),请通过itemdecoration你想要控制item增删的动画,请通过itemanimator你想要控制点击、长按事件,请自己写(擦,这点尼玛。)

基本使用

鉴于我们对于listview的使用特别的熟悉,对比下recyclerview的使用代码:

mrecyclerview = findview(r.id.id_recyclerview);
//设置布局管理器
mrecyclerview.setlayoutmanager(layout);
//设置adapter
mrecyclerview.setadapter(adapter)
//设置item增加、移除动画
mrecyclerview.setitemanimator(new defaultitemanimator());
//添加分割线
mrecyclerview.additemdecoration(new divideritemdecoration(
  getactivity(), divideritemdecoration.horizontal_list));

ok,相比较于listview的代码,listview可能只需要去设置一个adapter就能正常使用了。而recyclerview基本需要上面一系列的步骤,那么为什么会添加这么多的步骤呢?

那么就必须解释下recyclerview的这个名字了,从它类名上看,recyclerview代表的意义是,我只管recycler view,也就是说recyclerview只管回收与复用view,其他的你可以自己去设置。可以看出其高度的解耦,给予你充分的定制自由(所以你才可以轻松的通过这个控件实现listview,girdview,瀑布流等效果)。

just like listviewactivity

package com.zhy.sample.demo_recyclerview;
import java.util.arraylist;
import java.util.list;
import android.os.bundle;
import android.support.v7.app.actionbaractivity;
import android.support.v7.widget.linearlayoutmanager;
import android.support.v7.widget.recyclerview;
import android.support.v7.widget.recyclerview.viewholder;
import android.view.layoutinflater;
import android.view.view;
import android.view.viewgroup;
import android.widget.textview;
public class homeactivity extends actionbaractivity
{
 private recyclerview mrecyclerview;
 private list<string> mdatas;
 private homeadapter madapter;
 @override
 protected void oncreate(bundle savedinstancestate)
 {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.activity_single_recyclerview);
 initdata();
 mrecyclerview = (recyclerview) findviewbyid(r.id.id_recyclerview);
 mrecyclerview.setlayoutmanager(new linearlayoutmanager(this));
 mrecyclerview.setadapter(madapter = new homeadapter());
 }
 protected void initdata()
 {
 mdatas = new arraylist<string>();
 for (int i = 'a'; i < 'z'; i++)
 {
  mdatas.add("" + (char) i);
 }
 }
 class homeadapter extends recyclerview.adapter<homeadapter.myviewholder>
 {
 @override
 public myviewholder oncreateviewholder(viewgroup parent, int viewtype)
 {
  myviewholder holder = new myviewholder(layoutinflater.from(
   homeactivity.this).inflate(r.layout.item_home, parent,
   false));
  return holder;
 }
 @override
 public void onbindviewholder(myviewholder holder, int position)
 {
  holder.tv.settext(mdatas.get(position));
 }
 @override
 public int getitemcount()
 {
  return mdatas.size();
 }
 class myviewholder extends viewholder
 {
  textview tv;
  public myviewholder(view view)
  {
  super(view);
  tv = (textview) view.findviewbyid(r.id.id_num);
  }
 }
 }
}

activity的布局文件

<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" >
 <android.support.v7.widget.recyclerview
 android:id="@+id/id_recyclerview"
  android:divider="#ffff0000"
  android:dividerheight="10dp"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />
</relativelayout>

item的布局文件

<?xml version="1.0" encoding="utf-8"?>
<framelayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:background="#44ff0000"
 android:layout_height="wrap_content" >
 <textview
 android:id="@+id/id_num"
 android:layout_width="match_parent"
 android:layout_height="50dp"
 android:gravity="center"
 android:text="1" />
</framelayout>

这么看起来用法与listview的代码基本一致哈~~

看下效果图:

看起来好丑,item间应该有个分割线,当你去找时,你会发现recyclerview并没有支持divider这样的属性。那么怎么办,你可以给item的布局去设置margin,当然了这种方式不够优雅,我们文章开始说了,我们可以自由的去定制它,当然我们的分割线也是可以定制的。

itemdecoration

我们可以通过该方法添加分割线:

mrecyclerview.additemdecoration() 

该方法的参数为recyclerview.itemdecoration,该类为抽象类,官方目前并没有提供默认的实现类(我觉得最好能提供几个)。

该类的源码:

public static abstract class itemdecoration {
public void ondraw(canvas c, recyclerview parent, state state) {
   ondraw(c, parent);
 }
public void ondrawover(canvas c, recyclerview parent, state state) {
   ondrawover(c, parent);
 }
public void getitemoffsets(rect outrect, view view, recyclerview parent, state state) {
   getitemoffsets(outrect, ((layoutparams) view.getlayoutparams()).getviewlayoutposition(),
     parent);
}
@deprecated
public void getitemoffsets(rect outrect, int itemposition, recyclerview parent) {
   outrect.set(0, 0, 0, 0);
 }

当我们调用mrecyclerview.additemdecoration()方法添加decoration的时候,recyclerview在绘制的时候,去会绘制decorator,即调用该类的ondraw和ondrawover方法,

ondraw方法先于drawchildrenondrawover在drawchildren之后,一般我们选择复写其中一个即可。getitemoffsets 可以通过outrect.set()为每个item设置一定的偏移量,主要用于绘制decorator。

接下来我们看一个recyclerview.itemdecoration的实现类,该类很好的实现了recyclerview添加分割线(当使用layoutmanager为linearlayoutmanager时)。
该类参考自:divideritemdecoration

package com.zhy.sample.demo_recyclerview;
/*
 * copyright (c) 2014 the android open source project
 *
 * licensed under the apache license, version 2.0 (the "license");
 * limitations under the license.
 */
import android.content.context;
import android.content.res.typedarray;
import android.graphics.canvas;
import android.graphics.rect;
import android.graphics.drawable.drawable;
import android.support.v7.widget.linearlayoutmanager;
import android.support.v7.widget.recyclerview;
import android.support.v7.widget.recyclerview.state;
import android.util.log;
import android.view.view;
/**
 * this class is from the v7 samples of the android sdk. it's not by me!
 * <p/>
 * see the license above for details.
 */
public class divideritemdecoration extends recyclerview.itemdecoration {
 private static final int[] attrs = new int[]{
   android.r.attr.listdivider
 };
 public static final int horizontal_list = linearlayoutmanager.horizontal;
 public static final int vertical_list = linearlayoutmanager.vertical;
 private drawable mdivider;
 private int morientation;
 public divideritemdecoration(context context, int orientation) {
  final typedarray a = context.obtainstyledattributes(attrs);
  mdivider = a.getdrawable(0);
  a.recycle();
  setorientation(orientation);
 }
 public void setorientation(int orientation) {
  if (orientation != horizontal_list && orientation != vertical_list) {
   throw new illegalargumentexception("invalid orientation");
  }
  morientation = orientation;
 }
 @override
 public void ondraw(canvas c, recyclerview parent) {
  log.v("recyclerview - itemdecoration", "ondraw()");
  if (morientation == vertical_list) {
   drawvertical(c, parent);
  } else {
   drawhorizontal(c, parent);
  }
 }
 public void drawvertical(canvas c, recyclerview parent) {
  final int left = parent.getpaddingleft();
  final int right = parent.getwidth() - parent.getpaddingright();
  final int childcount = parent.getchildcount();
  for (int i = 0; i < childcount; i++) {
   final view child = parent.getchildat(i);
   android.support.v7.widget.recyclerview v = new android.support.v7.widget.recyclerview(parent.getcontext());
   final recyclerview.layoutparams params = (recyclerview.layoutparams) child
     .getlayoutparams();
   final int top = child.getbottom() + params.bottommargin;
   final int bottom = top + mdivider.getintrinsicheight();
   mdivider.setbounds(left, top, right, bottom);
   mdivider.draw(c);
  }
 }
 public void drawhorizontal(canvas c, recyclerview parent) {
  final int top = parent.getpaddingtop();
  final int bottom = parent.getheight() - parent.getpaddingbottom();
  final int childcount = parent.getchildcount();
  for (int i = 0; i < childcount; i++) {
   final view child = parent.getchildat(i);
   final recyclerview.layoutparams params = (recyclerview.layoutparams) child
     .getlayoutparams();
   final int left = child.getright() + params.rightmargin;
   final int right = left + mdivider.getintrinsicheight();
   mdivider.setbounds(left, top, right, bottom);
   mdivider.draw(c);
  }
 }
 @override
 public void getitemoffsets(rect outrect, int itemposition, recyclerview parent) {
  if (morientation == vertical_list) {
   outrect.set(0, 0, 0, mdivider.getintrinsicheight());
  } else {
   outrect.set(0, 0, mdivider.getintrinsicwidth(), 0);
  }
 }
}

该实现类可以看到通过读取系统主题中的 android.r.attr.listdivider作为item间的分割线,并且支持横向和纵向。如果你不清楚它是怎么做到的读取系统的属性用于自身,请参考我的另一篇博文:android 深入理解android中的自定义属性

获取到listdivider以后,该属性的值是个drawable,在getitemoffsets中,outrect去设置了绘制的范围。ondraw中实现了真正的绘制。

我们在原来的代码中添加一句:

mrecyclerview.additemdecoration(new divideritemdecoration(this,
divideritemdecoration.vertical_list));

ok,现在再运行,就可以看到分割线的效果了。

该分割线是系统默认的,你可以在theme.xml中找到该属性的使用情况。那么,使用系统的listdivider有什么好处呢?就是方便我们去随意的改变,该属性我们可以直接声明在:

<!-- application theme. -->
 <style name="apptheme" parent="appbasetheme">
  <item name="android:listdivider">@drawable/divider_bg</item> 
 </style>

然后自己写个drawable即可,下面我们换一种分隔符:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle" >
  <gradient
    android:centercolor="#ff00ff00"
    android:endcolor="#ff0000ff"
    android:startcolor="#ffff0000"
    android:type="linear" />
  <size android:height="4dp"/>
</shape>

现在的样子是:

当然了,你可以根据自己的需求,去随意的绘制,反正是画出来的,随便玩~~

ok,看到这,你可能觉得,这玩意真尼玛麻烦,完全不能比拟的心爱的listview。那么继续看。

layoutmanager

好了,上面实现了类似listview样子的demo,通过使用其默认的linearlayoutmanager。

recyclerview.layoutmanager吧,这是一个抽象类,好在系统提供了3个实现类:

linearlayoutmanager 现行管理器,支持横向、纵向。gridlayoutmanager 网格布局管理器staggeredgridlayoutmanager 瀑布就式布局管理器

上面我们已经初步体验了下linearlayoutmanager,接下来看gridlayoutmanager。

gridlayoutmanager

我们尝试去实现类似gridview,秒秒钟的事情:

//mrecyclerview.setlayoutmanager(new linearlayoutmanager(this));
    mrecyclerview.setlayoutmanager(new gridlayoutmanager(this,4));

只需要修改layoutmanager即可,还是很nice的。

当然了,改为gridlayoutmanager以后,对于分割线,前面的divideritemdecoration就不适用了,主要是因为它在绘制的时候,比如水平线,针对每个child的取值为:

final int left = parent.getpaddingleft();
final int right = parent.getwidth() - parent.getpaddingright();

因为每个item一行,这样是没问题的。而gridlayoutmanager时,一行有多个childitem,这样就多次绘制了,并且gridlayoutmanager时,item如果为最后一列(则右边无间隔线)或者为最后一行(底部无分割线)。

针对上述,我们编写了dividergriditemdecoration

package com.zhy.sample.demo_recyclerview;
import android.content.context;
import android.content.res.typedarray;
import android.graphics.canvas;
import android.graphics.rect;
import android.graphics.drawable.drawable;
import android.support.v7.widget.gridlayoutmanager;
import android.support.v7.widget.recyclerview;
import android.support.v7.widget.recyclerview.layoutmanager;
import android.support.v7.widget.recyclerview.state;
import android.support.v7.widget.staggeredgridlayoutmanager;
import android.view.view;
/**
 * 
 * @author zhy
 * 
 */
public class dividergriditemdecoration extends recyclerview.itemdecoration
{
  private static final int[] attrs = new int[] { android.r.attr.listdivider };
  private drawable mdivider;
  public dividergriditemdecoration(context context)
  {
    final typedarray a = context.obtainstyledattributes(attrs);
    mdivider = a.getdrawable(0);
    a.recycle();
  }
  @override
  public void ondraw(canvas c, recyclerview parent, state state)
  {
    drawhorizontal(c, parent);
    drawvertical(c, parent);
  }
  private int getspancount(recyclerview parent)
  {
    // 列数
    int spancount = -1;
    layoutmanager layoutmanager = parent.getlayoutmanager();
    if (layoutmanager instanceof gridlayoutmanager)
    {
      spancount = ((gridlayoutmanager) layoutmanager).getspancount();
    } else if (layoutmanager instanceof staggeredgridlayoutmanager)
    {
      spancount = ((staggeredgridlayoutmanager) layoutmanager)
          .getspancount();
    }
    return spancount;
  }
  public void drawhorizontal(canvas c, recyclerview parent)
  {
    int childcount = parent.getchildcount();
    for (int i = 0; i < childcount; i++)
    {
      final view child = parent.getchildat(i);
      final recyclerview.layoutparams params = (recyclerview.layoutparams) child
          .getlayoutparams();
      final int left = child.getleft() - params.leftmargin;
      final int right = child.getright() + params.rightmargin
          + mdivider.getintrinsicwidth();
      final int top = child.getbottom() + params.bottommargin;
      final int bottom = top + mdivider.getintrinsicheight();
      mdivider.setbounds(left, top, right, bottom);
      mdivider.draw(c);
    }
  }
  public void drawvertical(canvas c, recyclerview parent)
  {
    final int childcount = parent.getchildcount();
    for (int i = 0; i < childcount; i++)
    {
      final view child = parent.getchildat(i);
      final recyclerview.layoutparams params = (recyclerview.layoutparams) child
          .getlayoutparams();
      final int top = child.gettop() - params.topmargin;
      final int bottom = child.getbottom() + params.bottommargin;
      final int left = child.getright() + params.rightmargin;
      final int right = left + mdivider.getintrinsicwidth();
      mdivider.setbounds(left, top, right, bottom);
      mdivider.draw(c);
    }
  }
  private boolean islastcolum(recyclerview parent, int pos, int spancount,
      int childcount)
  {
    layoutmanager layoutmanager = parent.getlayoutmanager();
    if (layoutmanager instanceof gridlayoutmanager)
    {
      if ((pos + 1) % spancount == 0)// 如果是最后一列,则不需要绘制右边
      {
        return true;
      }
    } else if (layoutmanager instanceof staggeredgridlayoutmanager)
    {
      int orientation = ((staggeredgridlayoutmanager) layoutmanager)
          .getorientation();
      if (orientation == staggeredgridlayoutmanager.vertical)
      {
        if ((pos + 1) % spancount == 0)// 如果是最后一列,则不需要绘制右边
        {
          return true;
        }
      } else
      {
        childcount = childcount - childcount % spancount;
        if (pos >= childcount)// 如果是最后一列,则不需要绘制右边
          return true;
      }
    }
    return false;
  }
  private boolean islastraw(recyclerview parent, int pos, int spancount,
      int childcount)
  {
    layoutmanager layoutmanager = parent.getlayoutmanager();
    if (layoutmanager instanceof gridlayoutmanager)
    {
      childcount = childcount - childcount % spancount;
      if (pos >= childcount)// 如果是最后一行,则不需要绘制底部
        return true;
    } else if (layoutmanager instanceof staggeredgridlayoutmanager)
    {
      int orientation = ((staggeredgridlayoutmanager) layoutmanager)
          .getorientation();
      // staggeredgridlayoutmanager 且纵向滚动
      if (orientation == staggeredgridlayoutmanager.vertical)
      {
        childcount = childcount - childcount % spancount;
        // 如果是最后一行,则不需要绘制底部
        if (pos >= childcount)
          return true;
      } else
      // staggeredgridlayoutmanager 且横向滚动
      {
        // 如果是最后一行,则不需要绘制底部
        if ((pos + 1) % spancount == 0)
        {
          return true;
        }
      }
    }
    return false;
  }
  @override
  public void getitemoffsets(rect outrect, int itemposition,
      recyclerview parent)
  {
    int spancount = getspancount(parent);
    int childcount = parent.getadapter().getitemcount();
    if (islastraw(parent, itemposition, spancount, childcount))// 如果是最后一行,则不需要绘制底部
    {
      outrect.set(0, 0, mdivider.getintrinsicwidth(), 0);
    } else if (islastcolum(parent, itemposition, spancount, childcount))// 如果是最后一列,则不需要绘制右边
    {
      outrect.set(0, 0, 0, mdivider.getintrinsicheight());
    } else
    {
      outrect.set(0, 0, mdivider.getintrinsicwidth(),
          mdivider.getintrinsicheight());
    }
  }
}

主要在getitemoffsets方法中,去判断如果是最后一行,则不需要绘制底部;如果是最后一列,则不需要绘制右边,整个判断也考虑到了staggeredgridlayoutmanager的横向和纵向,所以稍稍有些复杂。最重要还是去理解,如何绘制什么的不重要。一般如果仅仅是希望有空隙,还是去设置item的margin方便。

最后的效果是:

ok,看到这,你可能还觉得recyclerview不够强大?

但是如果我们有这么个需求,纵屏的时候显示为listview,横屏的时候显示两列的gridview,我们recyclerview可以轻松搞定,而如果使用listview去实现还是需要点功夫的~~~

当然了,这只是皮毛,下面让你心服口服。

staggeredgridlayoutmanager

瀑布流式的布局,其实他可以实现gridlayoutmanager一样的功能,仅仅按照下列代码:

// mrecyclerview.setlayoutmanager(new gridlayoutmanager(this,4));
    mrecyclerview.setlayoutmanager(new staggeredgridlayoutmanager(4,    
		staggeredgridlayoutmanager.vertical));

这两种写法显示的效果是一致的,但是注意staggeredgridlayoutmanager构造的第二个参数传一个orientation,如果传入的是staggeredgridlayoutmanager.vertical代表有多少列;那么传入的如果是staggeredgridlayoutmanager.horizontal就代表有多少行,比如本例如果改为:

mrecyclerview.setlayoutmanager(new staggeredgridlayoutmanager(4,
    staggeredgridlayoutmanager.horizontal));

那么效果为:

可以看到,固定为4行,变成了左右滑动。有一点需要注意,如果是横向的时候,item的宽度需要注意去设置,毕竟横向的宽度没有约束了,应为控件可以横向滚动了。

如果你需要一样横向滚动的gridview,那么恭喜你。

ok,接下来准备看大招,如果让你去实现个瀑布流,最起码不是那么随意就可以实现的吧?但是,如果使用recyclerview,分分钟的事。

那么如何实现?其实你什么都不用做,只要使用staggeredgridlayoutmanager我们就已经实现了,只是上面的item布局我们使用了固定的高度,下面我们仅仅在适配器的onbindviewholder方法中为我们的item设置个随机的高度(代码就不贴了,最后会给出源码下载地址),看看效果图:

是不是棒棒哒,通过recyclerview去实现listview、gridview、瀑布流的效果基本上没有什么区别,而且可以仅仅通过设置不同的layoutmanager即可实现。

还有更nice的地方,就在于item增加、删除的动画也是可配置的。接下来看一下itemanimator。

itemanimator

itemanimator也是一个抽象类,好在系统为我们提供了一种默认的实现类,期待系统多
添加些默认的实现。

借助默认的实现,当item添加和移除的时候,添加动画效果很简单:

// 设置item动画
mrecyclerview.setitemanimator(new defaultitemanimator());

系统为我们提供了一个默认的实现,我们为我们的瀑布流添加以上一行代码,效果为:

如果是gridlayoutmanager呢?动画效果为:

注意,这里更新数据集不是用adapter.notifydatasetchanged()而是 notifyiteminserted(position)notifyitemremoved(position)

否则没有动画效果。

上述为adapter中添加了两个方法:

public void adddata(int position) {
    mdatas.add(position, "insert one");
    notifyiteminserted(position);
  }
  public void removedata(int position) {
      mdatas.remove(position);
    notifyitemremoved(position);
  }

activity中点击menuitem触发:

@override
  public boolean oncreateoptionsmenu(menu menu)
  {
    getmenuinflater().inflate(r.menu.main, menu);
    return super.oncreateoptionsmenu(menu);
  }
  @override
  public boolean onoptionsitemselected(menuitem item)
  {
    switch (item.getitemid())
    {
    case r.id.id_action_add:
      madapter.adddata(1);
      break;
    case r.id.id_action_delete:
      madapter.removedata(1);
      break;
    }
    return true;
  }

好了,到这我对这个控件已经不是一般的喜欢了~~~

当然了只提供了一种动画,那么我们肯定可以去自定义各种nice的动画效果。

高兴的是,github上已经有很多类似的项目了,这里我们直接引用下:recyclerviewitemanimators,大家自己下载查看。
提供了slideinoutleftitemanimator,slideinoutrightitemanimator,slideinouttopitemanimator,slideinoutbottomitemanimator等动画效果。

click and longclick

不过一个挺郁闷的地方就是,系统没有提供clicklistener和longclicklistener。
不过我们也可以自己去添加,只是会多了些代码而已。
实现的方式比较多,你可以通过mrecyclerview.addonitemtouchlistener去监听然后去判断手势,
当然你也可以通过adapter中自己去提供回调,这里我们选择后者,前者的方式,大家有兴趣自己去实现。

那么代码也比较简单:

class homeadapter extends recyclerview.adapter<homeadapter.myviewholder>
{
//...
  public interface onitemclicklitener
  {
    void onitemclick(view view, int position);
    void onitemlongclick(view view , int position);
  }
  private onitemclicklitener monitemclicklitener;
  public void setonitemclicklitener(onitemclicklitener monitemclicklitener)
  {
    this.monitemclicklitener = monitemclicklitener;
  }
  @override
  public void onbindviewholder(final myviewholder holder, final int position)
  {
    holder.tv.settext(mdatas.get(position));
    // 如果设置了回调,则设置点击事件
    if (monitemclicklitener != null)
    {
      holder.itemview.setonclicklistener(new onclicklistener()
      {
        @override
        public void onclick(view v)
        {
          int pos = holder.getlayoutposition();
          monitemclicklitener.onitemclick(holder.itemview, pos);
        }
      });
      holder.itemview.setonlongclicklistener(new onlongclicklistener()
      {
        @override
        public boolean onlongclick(view v)
        {
          int pos = holder.getlayoutposition();
          monitemclicklitener.onitemlongclick(holder.itemview, pos);
          return false;
        }
      });
    }
  }
//...
}

adapter中自己定义了个接口,然后在onbindviewholder中去为holder.itemview去设置相应
的监听最后回调我们设置的监听。

最后别忘了给item添加一个drawable:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
  <item android:state_pressed="true" android:drawable="@color/color_item_press"></item>
  <item android:drawable="@color/color_item_normal"></item>
</selector>

activity中去设置监听:

 madapter.setonitemclicklitener(new onitemclicklitener()
    {
      @override
      public void onitemclick(view view, int position)
      {
        toast.maketext(homeactivity.this, position + " click",
            toast.length_short).show();
      }
      @override
      public void onitemlongclick(view view, int position)
      {
        toast.maketext(homeactivity.this, position + " long click",
            toast.length_short).show();
            madapter.removedata(position);
      }
    });

测试效果:

ok,到此我们基本介绍了recylerview常见用法,包含了:

系统提供了几种layoutmanager的使用;如何通过自定义itemdecoration去设置分割线,或者一些你想作为分隔的drawable,注意这里巧妙的使用了系统的listdivider属性,你可以尝试添加使用divider和dividerheight属性。如何使用itemanimator为recylerview去添加item移除、添加的动画效果。介绍了如何添加itemclicklistener与itemlongclicklistener。

可以看到recyclerview可以实现:

listview的功能gridview的功能横向listview的功能,参考android 自定义recyclerview 实现真正的gallery效果横向scrollview的功能瀑布流效果便于添加item增加和移除动画

整个体验下来,感觉这种插拔式的设计太棒了,如果系统再能提供一些常用的分隔符,多添加些动画效果就更好了。

通过简单改变下layoutmanager,就可以产生不同的效果,那么我们可以根据手机屏幕的宽度去动态设置layoutmanager,屏幕宽度一般的,显示为listview;宽度稍大的显示两列的gridview或者瀑布流(或者横纵屏幕切换时变化,有点意思~);显示的列数和宽度成正比。甚至某些特殊屏幕,让其横向滑动~~再选择一个nice的动画效果,相信这种插件式的编码体验一定会让你迅速爱上recyclerview。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网