RecyclerView--个人使用心得

RecyclerView

RecyclerView的强大我就不在这里累赘了

看的是弘洋收入的博客
**如果你想再回顾一下 RecyclerView 的基本使用方法,推荐鸿洋的这篇文章:
《Android RecyclerView 使用完全解析 体验艺术般的控件》
http://blog.csdn.net/lmj623565791/article/details/45059587

1,item点击事件和item长点击事件

(1)自己写接口回调出来
RecyclerView 的 api 虽然没有提供 onItemClickListener 但是提供了 addOnItemTouchListener() 方法,既然可以添加触摸监听,那么我们完全可以获取触摸手势来识别点击事件,然后通过触摸坐标来判断点击的是哪一个item。
这里写图片描述

其中 OnRecyclerItemClickListener 是自定义的一个触摸监听器,GestureDetectorCompat 中传入了一个 ItemTouchHelperGestureListener,这里值得说的是:当获取到了 RecyclerView 的点击事件和触摸事件数据 MotionEvent,那么如何才能知道点击的是哪一个 item 呢?

RecyclerView已经为我们提供了这样的方法:findChildViewUnder()。

我们可以通过这个方法获得点击的 item ,同时我们调用 RecyclerView 的另一个方法 getChildViewHolder(),可以获得该 item 的 ViewHolder,最后再回调我们定义的虚方法 onItemClick() 就ok了,这样我们就可以在外部实现该方法来获得 item 的点击事件了。

(2)自己写接口回调出来

  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;
                }
            });
        }
    }
//...

2,添加 divider 的标准姿势

备注:recyclerview不能像ListView一样在xl设置divider
而是使用 mRecyclerView.addItemDecoration() 。 api添加decoretion
可以看这篇文章
《RecyclerView之ItemDecoration 讲解及高级特性实践》
http://www.10tiao.com/html/227/201705/2650239745/1.html

3,实现 item 的拖曳排序和滑动删除

主要就要使用到 ItemTouchHelper,ItemTouchHelper 一个帮助开发人员处理拖拽和滑动删除的实现类,它能够让你非常容易实现侧滑删除、拖拽的功能。

(ItemTouchHelper 的使用并不仅仅局限于 RecyclerView 的滑动删除,你同意可以用在其他需要拖曳滑动的地方。当然,今天我们不涉及其他地方的使用)

实现的代码并关联到 RecyclerView 非常简单,代码如下:

ItemTouchHelper itemTouchHelper 
        = new ItemTouchHelper(new ItemTouchHelper.Callback());
itemTouchHelper.attachToRecyclerView(mRecyclerView);

需要我们关注的是创建 ItemTouchHelper 时传入的参数 ItemTouchHelper.Callback() 。ItemTouchHelper 会在拖拽的时候回调 Callback 中相应的方法,我们只需在 Callback 中实现自己的逻辑。

自定义一个类继承实现 ItemTouchHelper.Callback 接口,需要实现以下方法:
这里写图片描述

getMovementFlags() 用于设置是否处理拖拽事件和滑动事件,以及拖拽和滑动操作的方向,有以下两种情况:

如果是列表类型的 RecyclerView,拖拽只有 UP、DOWN 两个方向
如果是网格类型的则有 UP、DOWN、LEFT、RIGHT 四个方向
该方法需要编写的代码如下:
这里写图片描述
dragFlags 是拖拽标志,
swipeFlags 是滑动标志,
swipeFlags 都设置为0,暂时不考虑滑动相关操作。

如果设置了相关的 dragFlags,那么当长按 item 的时候就会进入拖拽并在拖拽过程中不断回调 onMove() 方法,我们就在这个方法里获取当前拖拽的 item 和已经被拖拽到所处位置的 item 的ViewHolder,有了这2个 ViewHolder,我们就可以交换他们的数据集并调用 Adapter 的notifyItemMoved 方法来刷新 item。
这里写图片描述

只要重写完上面这两个方法,RecyclerView 就能实现拖曳的效果了。是不是很简单?

但是虽然拖曳是没什么问题了,但是并不能达到下图的效果,因为你正在拖曳的 item 并没有阴影效果。

那怎么才能实现被拖曳的 item 有背景颜色加深起到强调的视觉效果呢?这是需要重写下面两个方法:
这里写图片描述

滑动删除

如何实现滑动删除呢?我们只需要实现第三个方法 onSwipe() 就行了。

代码如下:
这里写图片描述
同时也不要忘了修改一下 getMovementFlags() 方法,以便能够相应滑动事件:
这里写图片描述

那目前你就能完美的实现拖曳排序和滑动删除了。

拖曳排序,首个固定

有时我们希望首个 item 不能被拖曳排序。比如我们在新闻 App 中常见当我们进行新闻分类时,“热门”新闻这个分类总是第一个且不能被拖曳修改,类似下面的效果:
那么怎么才能达到上面的效果呢?在上面我们的 Callback 类中有一个方法:

public boolean isLongPressDragEnabled() {
    return true;
}

这个方法是为了告诉 ItemTouchHelper 是否需要 RecyclerView 支持长按拖拽,默认返回是 ture,理所当然我们要支持,所以我们没有重写,因为默认true。

但是这样做是默认全部的item都可以拖拽,怎么实现部分item拖拽呢,在 isLongPressDragEnabled 方法的源码中有提示说,如果想自定义拖曳 view,那么就使用 startDrag(ViewHolder) 方法。

第一步:那么我们就先重写 isLongPressDragEnabled() 方法,返回 false 让它控制所有的 item 都不能拖曳。

public boolean isLongPressDragEnabled() {
    return false;
}

第二步:我们给 RecyclerView 设置 item 的长按监听事件,然后判断这个 item 是不是第一个(或者最后一个,如果你不想让最后一个被拖曳的话),如果不是我们就手动调用 startDrag(ViewHolder) 让 item 开始被拖曳。

结合上面我们提供的给 item 设置点击和长按事件的方法,我们可以这样:
这里写图片描述

第三步:如果你以为上面两步你就达到首个 item 固定不被拖曳的话,恭喜你,答对了!首个 item 确实固定不能被拖曳了,可是看看下图,就会令你大跌眼睛:
虽然我们通过上面两步控制了首个 item 不能被长按拖曳,但是我们并没有处理,别的 item 被拖曳到首个 item 的情况。那么如何才能让首个 item 不被挤掉呢,这个也很简单,只需要在 Callback 的 onMove() 方法中处理首个 item 被当着目标 item 的情况就行了。
这里写图片描述
好了,到这里就大功告成了。
可以看作者的源代码
https://github.com/OCNYang/RecyclerViewEvent
参考文章:
http://chuansong.me/n/400690551872
http://chuansong.me/n/400690851058
http://www.10tiao.com/html/227/201705/2650239745/1.html

阅读更多
文章标签: android
个人分类: Android-进阶
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭