神奇的ItemTouchHelper

XSize的主页

device-2018-03-30-193500.gif

本文知识点:

  • 常用API的说明
  • ItemTouchHelper的使用案例
  • 常见的使用案例

1.常用的API说明

  • getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) 主要的作用是用来返回可以滑动的方向,主要是处理滑动方向的!分为上下滑动和左右滑动使用makeMovementFlags(int dragFlags, int swipeFlags)进行相应的返回(具体怎么写,下面说)

    • 参数1:recyclerView对象
    • 参数2:本类中的ViewHolder对象
  • onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)当条目发生移动的时候回调这个方法,一般是通过Adapter的notifyItemMoved(int fromPosition, int toPosition)方法进行条目的互换(这里别忘了把List的相应条目互换,下面说怎么做)这里有个返回值,一定要确保返回true否则不会生效的。。。

    • 参数1:recyclerView对象
    • 参数2:原始的ViewHolder对象
    • 参数3:目标的ViewHolder对象
  • onSwiped(RecyclerView.ViewHolder viewHolder, int direction) 当条目达到删除条件的时候会调用,怎么理解呢?也就是滑动条目到达一半的时候会回调这个方法(一般是用作滑动删除的时候使用这个方法,使用notifyItemRemoved(int position)将条目进行删除,别忘了把数据源中的数据删除);

    • 参数1:相应的ViewHolder
    • 参数2:这个是获取的方向
  • isLongPressDragEnabled()是否长按才能操作,这里你要是返回ture代表必须通过长按才能操作,默认也是true,一般操作都是这样的。。。

  • boolean boolean isItemViewSwipeEnabled() 是否可以进行左右删除操作,默认返回true,也只有这个方法返回true的时候才会执行onSwiped(RecyclerView.ViewHolder viewHolder, int direction)方法

  • onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState)从静止状态变为其他状态的时候回调该方法

    • 参数1:ViewHolder对象
    • 参数2:表示当前的状态
  • clearView(RecyclerView recyclerView, ViewHolder viewHolder)当用户操作完毕某个item并且其动画也结束后会调用该方法,一般我们在该方法内恢复ItemView的初始状态,防止由于复用而产生的显示错乱问题。

  • onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)可以在这个方法内实现我们自定义的交互规则或者自定义的动画效果。

上面写了这么多的API相信大家已经烦了,但是我觉得去过这些API你不知道的话,真的没有办法好好理解下面的内容,所以我习惯把用到的API都先写出来,最起码混个脸熟。。。

下面进入到正题:实现RecyclerView的Item的处理,也就是最上面那种样式;

首先觉得CSDN_LQR在解耦和上做的很好,将相应的接口进行了拆分,自己也学习了一下这种思想,就是将相应的公共的内容通过接口进行连接;

1.相应的接口的实现

这里考虑到一个问题,首先在处理的时候都会处理相应的内容,有删除条目和条目互换的问题;所以这里通过接口的形式将关联放到相应的数据源处还是比较好的,这种思想可以借鉴一下。

public interface RecyclerItemHelper {
    //数据交换
    void onItemMove(int fromPosition, int toPosition);

    //数据删除
    void onItemDelete(int position);
}

2.实现相应的CallBack

public class RecyclerItemCallBack extends ItemTouchHelper.Callback {

    private static final String TAG = RecyclerItemHelper.class.getSimpleName();
    private RecyclerItemHelper mHelper;

    public RecyclerItemCallBack(RecyclerItemHelper helper) {
        mHelper = helper;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        Log.e(TAG, "getMovementFlags: ");
        //可以上下滑动
        int topAndBottom = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int leftAndRight = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        return makeMovementFlags(topAndBottom, leftAndRight);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        Log.e(TAG, "onMove: ");
        //这里是通过接口进行回调的
        mHelper.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        Log.e(TAG, "onSwiped: " + direction);
        mHelper.onItemDelete(viewHolder.getAdapterPosition());
    }
}

这里通过构造方法传递接口的形式(也就是上面的接口),将构造方法中传递进来,其实这里因为有两个是必须有的方法,如果是那种可以选择性实现的话,我会选择通过set的方法去添加接口。解释一下上面的代码,通过getMovementFlags()设置操作方向,当移动的时候
调用相应的回调方法,这里应该返回true确定回调触发了。如果你是左右滑动的时候,在滑动一半的时候会调用onSwiped()在这里确定了相应的删除操作。整体的逻辑就是这样,就是三个API的整合。

3.Apdpter的处理

class MainAdapter extends RecyclerView.Adapter<MainAdapter.Holder> implements RecyclerItemHelper {

    private List<String> mList;

    public MainAdapter(RecyclerView rvContent) {
        //先实例化Callback
        ItemTouchHelper.Callback callback = new RecyclerItemCallBack(this);
        //用Callback构造ItemtouchHelper
        ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
        //调用ItemTouchHelper的attachToRecyclerView方法建立联系
        touchHelper.attachToRecyclerView(rvContent);
    }

    public void setData(List<String> list) {
        if (null == list || list.size() == 0) return;
        mList = list;
        notifyDataSetChanged();
    }

    @Override
    public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false);
        return new Holder(itemView);
    }

    @Override
    public void onBindViewHolder(Holder holder, int position) {
        holder.mText.setText(mList.get(position));
    }

    @Override
    public int getItemCount() {
        return null != mList ? mList.size() : 0;
    }

    @Override
    public void onItemMove(int fromPosition, int toPosition) {
        Collections.swap(mList, fromPosition, toPosition);
        notifyItemMoved(fromPosition, toPosition);
    }

    @Override
    public void onItemDelete(int position) {
        Log.e("done", "onItemDelete: " + position);
        mList.remove(position);
        notifyItemRemoved(position);
    }

    public class Holder extends RecyclerView.ViewHolder {

        TextView mText;

        public Holder(View itemView) {
            super(itemView);
            mText = itemView.findViewById(R.id.tv_text);
        }
    }
}

这是Adapter的全部代码,和之前的写法没有什么区别,就是在构造方法中初始化并关联一个ItemTouchHelper就是那里面那三行代码,然后重写了两个函数,这里注意一个API就是Collections.swap(mList, fromPosition, toPosition);这个API是将list里面两个对象互换位置的API其他的就没有什么变化了。


基本上就这些代码,可以实现最上面的效果了。后续等有时间,研究一下侧拉删除的功能,如果你着急,可以看一下CSDN_LQR的文章讲到了这个功能!

特别感谢:
RecyclerView之使用ItemTouchHelper实现交互动画
CSDN_LQR关于ItemTouchHelper的讲解

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容