Android 实现RecyclerView 拖拽排序和右滑删除(高仿今日头条ItemTouchHelper详解

本文介绍如何使用RecyclerView结合ItemTouchHelper实现列表项拖拽功能。通过自定义Callback类及覆盖关键方法,如getMovementFlags、onMove等,实现不同布局下的拖拽效果,并提供拖拽时的视觉反馈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天和大家一起实现RecyclerView可拖拽Item,主要是使用RecyclerView结合ItemTouchHelper来实现的

这个类在v7包里面

 

 

 

实现步骤:

1.只需要给recyclerView添加一个ItemTouchHelper对象就行

mItemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() );

mItemTouchHelper.attachToRecyclerView(mRecyclerView);

2.ItemTouchHelper的callback

首先来自定义一个CallBack类,继承与ItemTouchHepler.Callback()对象

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

@Override

public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

  

}

 

@Override

public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {

   

   

}

 

@Override

public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

 

}

 

1).首先说一下getMovementFlags(),

这个方法是设置是否滑动时间,以及拖拽的方向,所以在这里需要判断一下是列表布局还是网格布局,

如果是列表布局的话则拖拽方向为DOWN和UP,如果是网格布局的话则是DOWN和UP和LEFT和RIGHT,对应这个方法的代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

@Override

            public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

                if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {

                    final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |

                            ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;

                    final int swipeFlags = 0;

                    return makeMovementFlags(dragFlags, swipeFlags);

                else {

                    final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;

                    final int swipeFlags = 0;

                    return makeMovementFlags(dragFlags, swipeFlags);

                }

            }

2).而onMove()方法则是我们在拖动的时候不断回调的方法,在这里我们需要将正在拖拽的item和集合的item进行交换元素,然后在通知适配器更新数据,也很简单,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

@Override

public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {

    //得到当拖拽的viewHolder的Position

    int fromPosition = viewHolder.getAdapterPosition();

    //拿到当前拖拽到的item的viewHolder

    int toPosition = target.getAdapterPosition();

    if (fromPosition < toPosition) {

        for (int i = fromPosition; i < toPosition; i++) {

            Collections.swap(datas, i, i + 1);

        }

    else {

        for (int i = fromPosition; i > toPosition; i--) {

            Collections.swap(datas, i, i - 1);

        }

    }

    myAdapter.notifyItemMoved(fromPosition, toPosition);

    return true;

}

3).onSwiped()是替换后调用的方法,可以不用管。然后我们希望在拖拽的时候将被拖拽的Item高亮,这样用户体验要好很多,所以我们要重写CallBack对象中的onSelectedChanged()和clearView()方法,在选中的时候设置高亮背景色,在完成的时候移除高亮背景色,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

/**

 * 长按选中Item的时候开始调用

 *

 * @param viewHolder

 * @param actionState

 */

@Override

public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {

    if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {

        viewHolder.itemView.setBackgroundColor(Color.LTGRAY);

    }

    super.onSelectedChanged(viewHolder, actionState);

}

 

/**

 * 手指松开的时候还原

 * @param recyclerView

 * @param viewHolder

 */

@Override

public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

    super.clearView(recyclerView, viewHolder);

    viewHolder.itemView.setBackgroundColor(0);

}

 

这样就实现了我们的基本要求,但是实际功能中有可能存在,排头前两个的不需改变它的顺序,即有些item允许拖拽,有些则不允许,所以我们需要重写isLongPressDragEnabled()设置不允许长按拖拽

1

2

3

4

5

6

7

8

/**

 * 重写拖拽不可用

 * @return

 */

@Override

public boolean isLongPressDragEnabled() {

    return false;

}

  然后在重写RecycleView的长按监听(这个要自己写个接口去实现),在返回的长按方法中判断是否为不可拖拽的item,若不是,则调用ItemTouchHelper的startDrag()方法,逻辑出入如下:

1

2

3

4

5

6

7

8

@Override

 public void onItemLongClick(RecyclerView.ViewHolder vh) {

     //判断被拖拽的是否是前两个,如果不是则执行拖拽

     if (vh.getLayoutPosition() != 0 && vh.getLayoutPosition() != 1) {

         mItemTouchHelper.startDrag(vh);

 

     }

 }

5.重要的拖动之后,数据变了。Adapter中实现下面的接口

 RecyclerView.Adapter
 @Override
    public void onMove(int fromPosition, int toPosition) {
        /**
         * 在这里进行给原数组数据的移动
         */
        Collections.swap(mData, fromPosition, toPosition);
        /**
         * 通知数据移动
         */
        notifyItemMoved(fromPosition, toPosition);
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值