【RecyclerView】使用完全指南(一)

转载注明出处:http://www.jianshu.com/p/4fc6164e4709

概述

官方介绍,RecyclerView用于在有限的窗口展现大量的数据,其实早已经有了类似的控件,如ListView、GridView,那么相比它们,RecyclerView有什么样优势呢?
RecyclerView标准化了ViewHolder,而且异常的灵活,可以轻松实现ListView实现不了的样式和功能,通过布局管理器LayoutManager可控制Item的布局方式,通过设置Item操作动画自定义Item添加和删除的动画,通过设置Item之间的间隔样式,自定义间隔。

  • 设置布局管理器以控制Item的布局方式,横向、竖向以及瀑布流方式。
  • 可设置Item操作的动画(删除或者添加等)
  • 可设置Item的间隔样式(可绘制)

但是关于Item的点击和长按事件,需要用户自己去实现。

在使用RecyclerView时候,必须指定一个适配器Adapter和一个布局管理器LayoutManager。适配器继承RecyclerView.Adapter类,具体实现类似ListView的适配器,取决于数据信息以及展示的UI。布局管理器用于确定RecyclerView中Item的展示方式以及决定何时复用已经不可见的Item,避免重复创建以及执行高成本的findViewById()方法。

来看一下用法。

mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// 设置布局管理器
mRecyclerView.setLayoutManager(mLayoutManager);
// 设置adapter
mRecyclerView.setAdapter(mAdapter);
// 设置Item添加和移除的动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
// 设置Item之间间隔样式
mRecyclerView.addItemDecoration(mDividerItemDecoration);

可以看见RecyclerView相比ListView会多出许多操作,这也是RecyclerView灵活的地方,它将许多动能暴露出来,用户可以选择性的自定义属性以满足需求。

RecyclerView提供了三种布局管理器:

  • LinerLayoutManager 以垂直或者水平列表方式展示Item
  • GridLayoutManager 以网格方式展示Item
  • StaggeredGridLayoutManager 以瀑布流方式展示Item

基本使用

在build.gradle文件中引入该类。

    compile 'com.android.support:recyclerview-v7:23.4.0'

Activity代码

public class MDRvActivity extends MDBaseActivity {
<span class="hljs-keyword">private</span> RecyclerView mRecyclerView;

<span class="hljs-keyword">private</span> RecyclerView.Adapter mAdapter;

<span class="hljs-keyword">private</span> RecyclerView.LayoutManager mLayoutManager;

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Bundle savedInstanceState)</span> </span>{
    <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
    setContentView(R.layout.activity_rv);
    initData();
    initView();
}

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initData</span><span class="hljs-params">()</span> </span>{
    mLayoutManager = <span class="hljs-keyword">new</span> LinearLayoutManager(<span class="hljs-keyword">this</span>, LinearLayoutManager.VERTICAL, <span class="hljs-keyword">false</span>);
    mAdapter = <span class="hljs-keyword">new</span> MyAdapter(getData());
}

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initView</span><span class="hljs-params">()</span> </span>{
    mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
    <span class="hljs-comment">// 设置布局管理器</span>
    mRecyclerView.setLayoutManager(mLayoutManager);
    <span class="hljs-comment">// 设置adapter</span>
    mRecyclerView.setAdapter(mAdapter);
}

<span class="hljs-function"><span class="hljs-keyword">private</span> ArrayList&lt;String&gt; <span class="hljs-title">getData</span><span class="hljs-params">()</span> </span>{
    ArrayList&lt;String&gt; data = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    String temp = <span class="hljs-string">" item"</span>;
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">20</span>; i++) {
        data.add(i + temp);
    }

    <span class="hljs-keyword">return</span> data;
}

}

Activity布局文件activity_rv.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

RecyclerView适配器Adapter代码

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
<span class="hljs-keyword">private</span> ArrayList&lt;String&gt; mData;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyAdapter</span><span class="hljs-params">(ArrayList&lt;String&gt; data)</span> </span>{
    <span class="hljs-keyword">this</span>.mData = data;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">updateData</span><span class="hljs-params">(ArrayList&lt;String&gt; data)</span> </span>{
    <span class="hljs-keyword">this</span>.mData = data;
    notifyDataSetChanged();
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> ViewHolder <span class="hljs-title">onCreateViewHolder</span><span class="hljs-params">(ViewGroup parent, <span class="hljs-keyword">int</span> viewType)</span> </span>{
    <span class="hljs-comment">// 实例化展示的view</span>
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_item, parent, <span class="hljs-keyword">false</span>);
    <span class="hljs-comment">// 实例化viewholder</span>
    ViewHolder viewHolder = <span class="hljs-keyword">new</span> ViewHolder(v);
    <span class="hljs-keyword">return</span> viewHolder;
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onBindViewHolder</span><span class="hljs-params">(ViewHolder holder, <span class="hljs-keyword">int</span> position)</span> </span>{
    <span class="hljs-comment">// 绑定数据</span>
    holder.mTv.setText(mData.get(position));
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getItemCount</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> mData == <span class="hljs-keyword">null</span> ? <span class="hljs-number">0</span> : mData.size();
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ViewHolder</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">RecyclerView</span>.<span class="hljs-title">ViewHolder</span> </span>{

    TextView mTv;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ViewHolder</span><span class="hljs-params">(View itemView)</span> </span>{
        <span class="hljs-keyword">super</span>(itemView);
        mTv = (TextView) itemView.findViewById(R.id.item_tv);
    }
}

}

Item的布局文件view_rv_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="@dimen/md_common_view_height">
    <TextView
        android:id="@+id/item_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        tools:text="item"/>
</LinearLayout>

运行结果如下:


RecyclerView-无间隔.jpg

可以看见展示效果和ListView基本上无差别,但是Item之间并没有分割线,在xml去找divider属性的时候,发现RecyclerView没有divider属性,当然也可以在Item布局中加上分割线,但是这样做并不是很优雅。前文说过,RecyclerView可是支持自定义间隔样式的。通过mRecyclerView.addItemDecoration()来设置我们定义好的间隔样式。

间隔样式

自定义间隔样式需要继承RecyclerView.ItemDecoration类,该类是个抽象类,主要有三个方法。

  • onDraw(Canvas c, RecyclerView parent, State state),在Item绘制之前被调用,该方法主要用于绘制间隔样式
  • onDrawOver(Canvas c, RecyclerView parent, State state),在Item绘制之后被调用,该方法主要用于绘制间隔样式
  • getItemOffsets(Rect outRect, View view, RecyclerView parent, State state),设置item的偏移量,偏移的部分用于填充间隔样式,在RecyclerView的onMesure()中会调用该方法

onDraw()onDrawOver()这两个方法都是用于绘制间隔样式,我们只需要复写其中一个方法即可。直接来看一下自定义的间隔样式的实现吧,参考官方实例

public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span>[] ATTRS = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[]{
        android.R.attr.listDivider
};
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> VERTICAL_LIST = LinearLayoutManager.VERTICAL;
<span class="hljs-comment">/**
 * 用于绘制间隔样式
 */</span>
<span class="hljs-keyword">private</span> Drawable mDivider;
<span class="hljs-comment">/**
 * 列表的方向,水平/竖直
 */</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mOrientation;


<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyDividerItemDecoration</span><span class="hljs-params">(Context context, <span class="hljs-keyword">int</span> orientation)</span> </span>{
    <span class="hljs-comment">// 获取默认主题的属性</span>
    <span class="hljs-keyword">final</span> TypedArray a = context.obtainStyledAttributes(ATTRS);
    mDivider = a.getDrawable(<span class="hljs-number">0</span>);
    a.recycle();
    setOrientation(orientation);
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onDraw</span><span class="hljs-params">(Canvas c, RecyclerView parent, RecyclerView.State state)</span> </span>{
    <span class="hljs-comment">// 绘制间隔</span>
    <span class="hljs-keyword">if</span> (mOrientation == VERTICAL_LIST) {
        drawVertical(c, parent);
    } <span class="hljs-keyword">else</span> {
        drawHorizontal(c, parent);
    }
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">getItemOffsets</span><span class="hljs-params">(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)</span> </span>{
    <span class="hljs-keyword">if</span> (mOrientation == VERTICAL_LIST) {
        outRect.set(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, mDivider.getIntrinsicHeight());
    } <span class="hljs-keyword">else</span> {
        outRect.set(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, mDivider.getIntrinsicWidth(), <span class="hljs-number">0</span>);
    }
}

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setOrientation</span><span class="hljs-params">(<span class="hljs-keyword">int</span> orientation)</span> </span>{
    <span class="hljs-keyword">if</span> (orientation != HORIZONTAL_LIST &amp;&amp; orientation != VERTICAL_LIST) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"invalid orientation"</span>);
    }
    mOrientation = orientation;
}

<span class="hljs-comment">/**
 * 绘制间隔
 */</span>
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">drawVertical</span><span class="hljs-params">(Canvas c, RecyclerView parent)</span> </span>{
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> left = parent.getPaddingLeft();
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> right = parent.getWidth() - parent.getPaddingRight();
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> childCount = parent.getChildCount();
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; childCount; i++) {
        <span class="hljs-keyword">final</span> View child = parent.getChildAt(i);
        <span class="hljs-keyword">final</span> RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                .getLayoutParams();
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> top = child.getBottom() + params.bottomMargin +
                Math.round(ViewCompat.getTranslationY(child));
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> bottom = top + mDivider.getIntrinsicHeight();
        mDivider.setBounds(left, top, right, bottom);
        mDivider.draw(c);
    }
}

<span class="hljs-comment">/**
 * 绘制间隔
 */</span>
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">drawHorizontal</span><span class="hljs-params">(Canvas c, RecyclerView parent)</span> </span>{
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> top = parent.getPaddingTop();
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> bottom = parent.getHeight() - parent.getPaddingBottom();
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> childCount = parent.getChildCount();
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; childCount; i++) {
        <span class="hljs-keyword">final</span> View child = parent.getChildAt(i);
        <span class="hljs-keyword">final</span> RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                .getLayoutParams();
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> left = child.getRight() + params.rightMargin +
                Math.round(ViewCompat.getTranslationX(child));
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> right = left + mDivider.getIntrinsicHeight();
        mDivider.setBounds(left, top, right, bottom);
        mDivider.draw(c);
    }
}

}

然后在代码中设置RecyclerView的间隔样式。

mRecyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL));

来看一下展示效果。

RecyclerView-有间隔.jpg

既然RecyclerView还支持水平列表,简单改一下属性,看看水平列表的显示效果。

修改Item的布局文件view_rv_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="vertical"
              android:layout_width="@dimen/md_common_view_width"
              android:layout_height="match_parent">
    <TextView
        android:id="@+id/item_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
    tools:text=<span class="hljs-string">"item"</span>/&gt;

</LinearLayout>

修改LayoutManager的初始化和间隔样式初始化。

mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
// 设置Item之间间隔样式
mRecyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.HORIZONTAL));

看一下水平列表效果。


RecyclerView-水平列表.jpg

动画

前面说过,RecyclerView可以设置列表中Item删除和添加的动画,在v7包中给我们提供了一种默认的Item删除和添加的动画,如果没有特殊的需求,默认使用这个动画即可。

// 设置Item添加和移除的动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());

下面就添加一下删除和添加Item的动作。在Adapter里面添加方法。

public void addNewItem() {
    if(mData == null) {
        mData = new ArrayList<>();
    }
    mData.add(0, "new Item");
    notifyItemInserted(0);
}

public void deleteItem() {
if(mData == null || mData.isEmpty()) {
return;
}
mData.remove(0);
notifyItemRemoved(0);
}

添加事件的处理。

public void onClick(View v) {
    int id = v.getId();
    if(id == R.id.rv_add_item_btn) {
        mAdapter.addNewItem();
        // 由于Adapter内部是直接在首个Item位置做增加操作,增加完毕后列表移动到首个Item位置
        mLayoutManager.scrollToPosition(0);
    } else if(id == R.id.rv_del_item_btn){
        mAdapter.deleteItem();
        // 由于Adapter内部是直接在首个Item位置做删除操作,删除完毕后列表移动到首个Item位置
        mLayoutManager.scrollToPosition(0);
    }
}

准备工作完毕后,来看一下运行的效果。

RecyclerView-动画.gif

点击事件

RecyclerView并没有像ListView一样暴露出Item点击事件或者长按事件处理的api,也就是说使用RecyclerView时候,需要我们自己来实现Item的点击和长按等事件的处理。实现方法有很多,可以监听RecyclerView的Touch事件然后判断手势做相应的处理,也可以通过在绑定ViewHolder的时候设置监听,然后通过Apater回调出去,我们选择第二种方法,更加直观和简单。

看一下Adapter的完整代码。

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
<span class="hljs-comment">/**
 * 展示数据
 */</span>
<span class="hljs-keyword">private</span> ArrayList&lt;String&gt; mData;

<span class="hljs-comment">/**
 * 事件回调监听
 */</span>
<span class="hljs-keyword">private</span> MyAdapter.OnItemClickListener onItemClickListener;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyAdapter</span><span class="hljs-params">(ArrayList&lt;String&gt; data)</span> </span>{
    <span class="hljs-keyword">this</span>.mData = data;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">updateData</span><span class="hljs-params">(ArrayList&lt;String&gt; data)</span> </span>{
    <span class="hljs-keyword">this</span>.mData = data;
    notifyDataSetChanged();
}

<span class="hljs-comment">/**
 * 添加新的Item
 */</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addNewItem</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">if</span>(mData == <span class="hljs-keyword">null</span>) {
        mData = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    }
    mData.add(<span class="hljs-number">0</span>, <span class="hljs-string">"new Item"</span>);
    notifyItemInserted(<span class="hljs-number">0</span>);
}

<span class="hljs-comment">/**
 * 删除Item
 */</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deleteItem</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">if</span>(mData == <span class="hljs-keyword">null</span> || mData.isEmpty()) {
        <span class="hljs-keyword">return</span>;
    }
    mData.remove(<span class="hljs-number">0</span>);
    notifyItemRemoved(<span class="hljs-number">0</span>);
}

<span class="hljs-comment">/**
 * 设置回调监听
 * 
 * <span class="hljs-doctag">@param</span> listener
 */</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setOnItemClickListener</span><span class="hljs-params">(MyAdapter.OnItemClickListener listener)</span> </span>{
    <span class="hljs-keyword">this</span>.onItemClickListener = listener;
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> ViewHolder <span class="hljs-title">onCreateViewHolder</span><span class="hljs-params">(ViewGroup parent, <span class="hljs-keyword">int</span> viewType)</span> </span>{
    <span class="hljs-comment">// 实例化展示的view</span>
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_item, parent, <span class="hljs-keyword">false</span>);
    <span class="hljs-comment">// 实例化viewholder</span>
    ViewHolder viewHolder = <span class="hljs-keyword">new</span> ViewHolder(v);
    <span class="hljs-keyword">return</span> viewHolder;
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onBindViewHolder</span><span class="hljs-params">(<span class="hljs-keyword">final</span> ViewHolder holder, <span class="hljs-keyword">int</span> position)</span> </span>{
    <span class="hljs-comment">// 绑定数据</span>
    holder.mTv.setText(mData.get(position));

    holder.itemView.setOnClickListener(<span class="hljs-keyword">new</span> View.OnClickListener() {
        <span class="hljs-meta">@Override</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span><span class="hljs-params">(<span class="hljs-keyword">final</span> View v)</span> </span>{
            <span class="hljs-keyword">if</span>(onItemClickListener != <span class="hljs-keyword">null</span>) {
                <span class="hljs-keyword">int</span> pos = holder.getLayoutPosition();
                onItemClickListener.onItemClick(holder.itemView, pos);
            }
        }
    });

    holder.itemView.setOnLongClickListener(<span class="hljs-keyword">new</span> View.OnLongClickListener() {
        <span class="hljs-meta">@Override</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">onLongClick</span><span class="hljs-params">(View v)</span> </span>{
            <span class="hljs-keyword">if</span>(onItemClickListener != <span class="hljs-keyword">null</span>) {
                <span class="hljs-keyword">int</span> pos = holder.getLayoutPosition();
                onItemClickListener.onItemLongClick(holder.itemView, pos);
            }
            <span class="hljs-comment">//表示此事件已经消费,不会触发单击事件</span>
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        }
    });
}

<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getItemCount</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> mData == <span class="hljs-keyword">null</span> ? <span class="hljs-number">0</span> : mData.size();
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ViewHolder</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">RecyclerView</span>.<span class="hljs-title">ViewHolder</span> </span>{

    TextView mTv;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ViewHolder</span><span class="hljs-params">(View itemView)</span> </span>{
        <span class="hljs-keyword">super</span>(itemView);
        mTv = (TextView) itemView.findViewById(R.id.item_tv);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">OnItemClickListener</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">onItemClick</span><span class="hljs-params">(View view, <span class="hljs-keyword">int</span> position)</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">onItemLongClick</span><span class="hljs-params">(View view, <span class="hljs-keyword">int</span> position)</span></span>;
}

}

设置Adapter的事件监听。

mAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(View view, int position) {
        Toast.makeText(MDRvActivity.this,"click " + position + " item", Toast.LENGTH_SHORT).show();
    }
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onItemLongClick</span><span class="hljs-params">(View view, <span class="hljs-keyword">int</span> position)</span> </span>{
    Toast.makeText(MDRvActivity.<span class="hljs-keyword">this</span>,<span class="hljs-string">"long click "</span> + position + <span class="hljs-string">" item"</span>, Toast.LENGTH_SHORT).show();
}

});

最后的实现效果。


RecyclerView-点击.gif

总结

可以看见相比于ListView,RecyclerView非常灵活,但其实这篇文章只是介绍了RecyclerView的基本使用,并没有深入,比如像网格展示和瀑布流展示都没有介绍,而且这篇文章为了详细的介绍使用方法,贴了大量的源代码,导致篇幅过长,不得以要将RecyclerView的使用分好几篇来介绍。就目前而言,我们已经知道RecyclerView的一些功能如下。

  • 水平列表展示,设置LayoutManager的方向性
  • 竖直列表展示,设置LayoutManager的方向性
  • 自定义间隔,RecyclerView.addItemDecoration()
  • Item添加和删除动画,RecyclerView.setItemAnimator()

所以在项目中如果再遇见列表类的布局,就可以优先考虑使用RecyclerView,更灵活更快捷的使用方式会给编码带来不一样的体验。如果你以为这些就是RecyclerView相比ListView/GridView优势的话,那就大错特错了,关于RecyclerView还有更多灵活的功能,在后面文章会慢慢介绍。

Demo地址

下一篇会主要介绍RecyclerView的其他两种展示方式,网格和瀑布流。

      </div>
    </div>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值