RecyclerView详细解释


RecyclerView简单介绍

RecyclerView是一个高度的解耦,异常的灵活的View,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。

RecyclerView与老前辈ListView的不同点,主要在于以下几个特性:

Adapter中的ViewHolder模式 ­ 对于ListView来说,通过创建 ViewHolder 来提升性能并不是必须的。因为ListView并没有严格的ViewHolder设计模式。但是在使用RecyclerView的时候,Adapter 必须实现至少一个ViewHolder,必须遵循ViewHolder设计模式。

定制Item条目 ­ ListView只能实现垂直线性排列的列表视图,与之不同的是,RecyclerView可以通过设置RecyclerView.LayoutManager来定制不同风格的视图,比如水平滚动列表或者不规则的瀑布流列表。

tem动画 ­ 在ListView中没有提供任何方法或者接口,方便开发者实现Item的增删动画。相反地,可以通过设置RecyclerView的 RecyclerView.ItemAnimator 来为条目增加动画效果。

设置数据源 ­ 在LisView中针对不同数据封装了各种类型的 Adapter ,比如用来处理数组的 ArrayAdapter 和用来展示Database结果的 CursorAdapter 。相反地,在RecyclerView中必须自定义实现 RecyclerView.Adapter 并为其提供数据集合。

设置条目分割线 ­ 在ListView中可以通过设置 android:divider 属性来为两个Item间设置分割线。如果想为RecyclerView添加此效果,则必须使用 RecyclerView.ItemDecoration ,这种实现方式不仅更灵活,而且样式也更加丰富。

设置点击事件 ­ 在ListView中存在 AdapterView.OnItemClickListener 接口,用来绑定条目的点击事件。但是,很遗憾的是在RecyclerView中,并没有提供这样的接口,不过,提供了另外一个接口 RcyclerView.OnItemTouchListener ,用来响应条目的触摸事件。

RecyclerView简单使用

一个是在Gradle中直接添加:

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

版本号不用找,仿照上面的appcompat直接用,把appcompat改成recyclerview即可

    compile 'com.android.support:appcompat-v7:24.2.1'

第二种是在Design面板直接拖拽,会提示你添加

核心类的介绍

RecyclerView的任务仅限于回收和定位屏幕上的View。 View能够显示数据还离不开另外两个类的支持:Adapter子类和ViewHolder子类。

RecyclerView.Adapter  ­ 处理数据集合并负责绑定视图

ViewHolder  ­ 持有所有的用于绑定数据或者需要操作的View

LayoutManager  ­ 负责摆放视图等相关操作

ItemDecoration  ­ 负责绘制Item附近的分割线

ItemAnimator  ­ 为Item的一般操作添加动画效果,如,增删条目等

ViewHolder

ViewHolder只做一件事:容纳View视图

RecyclerView自身不会创建视图,它创建的是ViewHolder,而ViewHolder引用着一个个itemView,如下图:

可以通过打印 ViewHolder.toString 来获取更多有效信息

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("ViewHolder{" +
                    Integer.toHexString(hashCode()) + " position=" + mPosition + " id=" + mItemId +
                    ", oldPos=" + mOldPosition + ", pLpos:" + mPreLayoutPosition);
            if (isScrap()) {
                sb.append(" scrap ")
                        .append(mInChangeScrap ? "[changeScrap]" : "[attachedScrap]");
            }
            if (isInvalid()) sb.append(" invalid");
            if (!isBound()) sb.append(" unbound");
            if (needsUpdate()) sb.append(" update");
            if (isRemoved()) sb.append(" removed");
            if (shouldIgnore()) sb.append(" ignored");
            if (isTmpDetached()) sb.append(" tmpDetached");
            if (!isRecyclable()) sb.append(" not recyclable(" + mIsRecyclableCount + ")");
            if (isAdapterPositionUnknown()) sb.append(" undefined adapter position");
​
            if (itemView.getParent() == null) sb.append(" no parent");
            sb.append("}");
            return sb.toString();
        }

Adapter

Adapter是个控制器对象,从模型层获取数据,然后提供给RecyclerView显示,起到了沟通的桥梁作用,adapter负责: 1、创建必要的ViewHolder; 2、 绑定ViewHolder至模型层数据。

public VH onCreateViewHolder(ViewGroup parent, int viewType)  创建Item视图,并返回相应的ViewHolder

public void onBindViewHolder(VH holder, int position)  绑定数据到正确的Item视图上。

public int getItemCount()  返回该Adapter所持有的Itme数量

要创建adapter, 首先要定义RecyclerView.Adapter子类,RecyclerView需要显示视图对象时, 就会去找它的adapter,如下图:

首先,通过调用adapter的getItemCount()方法,RecyclerView询问数组列表中包含多少个对象。 接 着 , RecyclerView 调 用 adapter 的 createViewHolder(ViewGroup, int) 方 法 创 建ViewHolder以及ViewHolder要显示的视图。 最后, RecyclerView会传入ViewHolder及其位置, 调用onBindViewHolder(ViewHolder, int)方法。adapter会找到目标位置的数据并绑定到ViewHolder的视图上。所谓绑定,就是使用模型数据填充视图。 整个过程执行完毕,RecyclerView就能在屏幕上显示crime列表项了。需要注意的是,相对于onBindViewHolder(ViewHolder, int)方法,createViewHolder(ViewGroup, int)方法的调用并不频繁。一旦创建了够用的ViewHolder,RecyclerView就会停止调用createView Holder(...)方法。然后,通过回收利用旧的ViewHolder节约时间和内存。

开始使用

首先创建一个JavaBean负责模拟数据

public class JavaBean {
    String name;
    int age;
​
    public JavaBean(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

然后在根据上面的两种方式添加依赖,之后设置控制器:

/**
 * @author HaoTianYi hao.ty@haotianyi.win
 * @version v1.0
 * @des   一个作用是初始化UI、一个是负责更新数据
 * @time 2016-11-10 18:54
 */public class MyHolder extends RecyclerView.ViewHolder {
​
    private TextView mTvAge;
    private TextView mTvName;
​
    public MyHolder(View itemView) {
        super(itemView);
//      初始化View
        mTvAge = (TextView) itemView.findViewById(R.id.age);
        mTvName = (TextView) itemView.findViewById(R.id.name);
    }
​
    /**
     * 负责更新数据也就是刷新UI
     * @param bean  数据
     * @call 由MyAdapter的onBindViewHolder方法调用
     */
    public void bindData(JavaBean bean) {
        mTvAge.setText(" "+bean.age);
        mTvName.setText(bean.name);
    }
}

设置内容填充者:

/**
 * @author HaoTianYi hao.ty@haotianyi.win
 * @version v1.0
 * @des   从模型层拿到数据并且传递给RecyclerView(中间人的角色)
 * @time 2016-11-10 18:54
 */public class MyAdapter extends RecyclerView.Adapter<MyHolder> {
​
    private List<JavaBean> mBeen;
​
    public MyAdapter(List<JavaBean> been) {
        mBeen = been;
    }
​
    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//      可以从parent得到context,没有必要在传递一个context参数
//      这里的父布局参数是null
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, null);
        return new MyHolder(itemView);
    }
​
    /**
     * 一旦创建填充满屏幕的item之后,在滑动item就会复用
     * 也就是不再调用onCreateViewHolder而是调用onBindViewHolder
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(MyHolder holder, int position) {
//      用控制器控制数据
        holder.bindData(mBeen.get(position));
    }
​
    @Override
    public int getItemCount() {
        return mBeen.size();
    }
}

Activity的使用代码:

public class MainActivity extends AppCompatActivity {
​
    private List<JavaBean> mBeen = new ArrayList<JavaBean>();
    private final String NAME = "普朗特";
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }
​
    private void init() {
//      模拟数据
        for (int i = 0; i < 50; i++) {
            JavaBean javaBean = new JavaBean(NAME + i, i);
            mBeen.add(javaBean);
        }
​
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv);
        recyclerView.setAdapter(new MyAdapter(mBeen));
//      一定要设置布局,否则不会显示内容
        recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
    }
}

相比ListView而言,RecyclerView的每一个类都是真是职责超级单一啊!!!

最后放上item的代码:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/name"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:text="nihao"
        android:textSize="20sp"/>
    <TextView
        android:id="@+id/age"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:text="llll"
        android:textSize="20sp"/>
</LinearLayout>

布局管理LayoutManager

布局管理的基类是RecyclerView.LayoutManager(抽象类)

LinearLayoutManager 线性管理器,支持横向、纵向。GridLayoutManager 网格布局管理器StaggeredGridLayoutManager 瀑布式布局管理器

改变上面的代码,瞬间实现水平滚动:

        LinearLayoutManager manager = new LinearLayoutManager(MainActivity.this);
        manager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(manager);

实现网格管理器,每一行4列

recyclerView.setLayoutManager(new GridLayoutManager(MainActivity.this,4));

瀑布流管理器,当第二个参数设置成Vertical时和上面一样:

recyclerView.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL));

当设置成HORIZONTAL变成水平是4行,这时是水平滑动的,item的宽度需要注意去设置,毕竟横向的宽度没有约束了,应为控件可以横向滚动了。,这里没有严重的变形是因为字体设置了大小

常用API

findFirstVisibleItemPosition()  返回当前第一个可见Item的positionfindFirstCompletelyVisibleItemPosition()  返回当前第一个完全可见Item的positionfindLastVisibleItemPosition()  返回当前最后一个可见Item的positionfindLastCompletelyVisibleItemPosition()  返回当前最后一个完全可见Item的position

设置一个瀑布流式的布局

要把每个item的高度不固定,即可实现,首先改Adapter中的onCreateViewHolder方法

    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//      可以从parent得到context,没有必要在传递一个context参数
//      这里的父布局参数是null
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, null);
        //设置随机高度
        int height = (int) (Math.random() * 100);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(954/4,300+height);
        params.setMargins(10,10,10,10);
        itemView.setLayoutParams(params);
​
        return new MyHolder(itemView);
    }

Activity中的引用代码不变:

        StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(manager);

这时可以实现,但是每一个item在一会就会改变,而且有动画效果

可以看到在滑动时候会有布局的变化,重写Adapter中的getItemViewType可以使每一个item固定

    @Override
    public int getItemViewType(int position) {
        return position;
    }

现在是没有布局变化了

分隔条RecyclerView.ItemDecoration

通过设置 recyclerView.addItemDecoration(new DividerDecoration(this)); 来改变Item之间的偏移量或者对Item进行装饰。

RecyclerView.ItemDecoration 是一个抽象类,可以通过重写以下三个方法,来实现Item之间的偏移量或者装饰效果:public void onDraw(Canvas c, RecyclerView parent)  装饰的绘制在Item条目绘制之前调用,所以这有可能被Item的内容所遮挡public void onDrawOver(Canvas c, RecyclerView parent)  装饰的绘制在Item条目绘制之后调用,因此装饰将浮于Item之上public  void  getItemOffsets(Rect  outRect,  int  itemPosition,  RecyclerView  parent)   与 padding 或 margin 类 似 ,LayoutManager在测量阶段会调用该方法,计算出每一个Item的正确尺寸并设置偏移量。

具体使用

public class DividerItemDecoration extends RecyclerView.ItemDecoration {
    /**
     * 设置一个属性集合,可以在自己的attrs中自行设置
     */
    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;
    /**
     * 分割符的Drawable
     */
    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) {
        System.out.println("recyclerview - itemdecoration   onDraw()");
​
        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }
​
    }
​
    /**
     * 绘制垂直分割符(如果是垂直滑动的话)
     * @param c
     * @param 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);
        }
    }
​
    /**
     *  绘制水平分割符(如果是水平滑动的话)
     * @param c
     * @param parent
     */
    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);
        }
    }
}

在上面的代码中更改Activity中的代码:

recyclerView.addItemDecoration(new DividerItemDecoration(MainActivity.this,DividerItemDecoration.VERTICAL_LIST));

自定义分割符

只要在attrs中添加一个android:listDivider属性即可,其余全部是自动生成的:

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:listDivider">@drawable/divider_item</item>
    </style>

对应的自定义divider_item.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <size android:width="3dp" android:height="3dp"/>
    <solid android:color="@color/colorPrimaryDark"/>
</shape>

最简单的分割符

如果只是想设置一个空余的间距,在Adapter中设置margin跟少的代码量,改变adapter中的onCreateViewHolder方法:

    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//      可以从parent得到context,没有必要在传递一个context参数
//      这里的父布局参数是null
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, null);
        
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(parent.getWidth(),150);
        params.setMargins(10,10,10,10);
        itemView.setLayoutParams(params);
        
        return new MyHolder(itemView);
    }

网格布局中的分隔符实例

参考:csdn

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)
    {
​
        drawHorizontal(c, parent);
        drawVertical(c, parent);
​
    }
​
    private int getSpanCount(RecyclerView parent)
    {
        // 列数
        int spanCount = -1;
        RecyclerView.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)
    {
        RecyclerView.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)
    {
        RecyclerView.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());
        }
    }

动画RecyclerView.ItemAnimator

在Android中默认实现了一个 DefaultItemAnimator

ItemAnimator能够帮助Item实现独立的动画,ItemAnimator作触发于以下三种事件:

  1. 某条数据被插入到数据集合中
  2. 从数据集合中移除某条数据
  3. 更改数据集合中的某条数据

事件监听listener

public void setOnItemClickListener(@Nullable OnItemClickListener listener)  Item点击事件监听public void setOnItemLongClickListener(OnItemLongClickListener listener)  Item长按事件监听

首先在Adapter中设置一个回调接口,添加OnItemClickListener接口,更改onBindViewHolder方法

    private OnItemClickListener mOnItemClickListener;
​
     interface OnItemClickListener {
//      点击事件
        void onItemClick(View view, int position);
//      长按事件
        void onItemLongClick(View view, int position);
    }
​
    public void setOnItemClickLitener(OnItemClickListener mLitener) {
        mOnItemClickListener = mLitener;
    }
​
    /**
     * 一旦创建填充满屏幕的item之后,在滑动item就会复用
     * 也就是不再调用onCreateViewHolder而是调用onBindViewHolder
     *
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(final MyHolder holder, final int position) {
//      用控制器控制数据
        System.out.println(holder.toString());
        holder.bindData(mBeen.get(position));
​
        if (mOnItemClickListener != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mOnItemClickListener.onItemClick(holder.itemView, position);
                }
            });
​
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    mOnItemClickListener.onItemLongClick(holder.itemView, position);
                    return true;
                }
            });
        }
    }

在Activity中设置监听:

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv);
        mAdapter = new MyAdapter(mBeen);
        mAdapter.setOnItemClickLitener(new MyAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                System.out.println("-----"+"onItemClick"+"-----");
            }
​
            @Override
            public void onItemLongClick(View view, int position) {
                System.out.println("-----"+"onItemLongClick"+"-----");
            }
        });
        recyclerView.setAdapter(mAdapter);

触发事件,可以看到结果:

参考RecyclerView


It's time for you to begin thinking out of the box