RecyclerView系列--用ItemTouchHelper实现一个支持上下移动和滑动删除的列表

列表的上下移动和滑动删除是不是经常看到,如何实现呢?其实使用ItemTouchHelper可以轻松实现。闲话不多说,先看效果。
这里写图片描述

先看一下官方的介绍

This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.
It works with a RecyclerView and a Callback class, which configures what type of interactions
are enabled and also receives events when user performs these actions.

它是一个RecyclerView添加条目滑动和拖拽的扩展工具类,它需要和一个回调类配合工作,通过配置交互方式的启用以及当我们执行操作时接受这些事件。
官方的构造方法是这样说的

/**
  * Creates an ItemTouchHelper that will work with the given Callback.
  * <p>
  * You can attach ItemTouchHelper to a RecyclerView via
  * {@link #attachToRecyclerView(RecyclerView)}. Upon attaching, it will add an item decoration,
  * an onItemTouchListener and a Child attach / detach listener to the RecyclerView.
  *
  * @param callback The Callback which controls the behavior of this touch helper.
  */
 public ItemTouchHelper(Callback callback) {
     mCallback = callback;
 }

看到这里的介绍你是不是一目了然了,还等什么,行动起来。

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

接下来我们要自定义一个Callback来开启一个交互方式权限并执行一些用户操作。

API介绍:

  • getMovementFlags
    它是一个抽象方法,返回自己所需要支持的移动方法的flags,通过官方的注释可以看到你可以使用makeMovementFlags创建你所需要支持的dragFlags和moveFlags
  • onMove
    执行上下移动的操作,返回值是否移动。
  • onSwiped
    执行左右滑动的操作
  • isLongPressDragEnabled
    是否支持长按拖拽
    上面的几个方法就可以实现上下移动和左右滑动效果。
    如何实现上下滑动?
    首先我们需要支持上下滑动
 int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = 0;
        int result = makeMovementFlags(dragFlags, swipeFlags);

其次是处理上下移动的事件,onMove给我们提供很方便的回调。

public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder srcViewHolder,
                      RecyclerView.ViewHolder targetViewHolder){

    boolean result = itemTouchMoveListener.onItemMove(srcViewHolder.getAdapterPosition(),
            targetViewHolder.getAdapterPosition());
    return result;
}

srcViewHolder : 是按住的那个条目
targetViewHolder: 移动到的那个条目
得到这两个条目的位置,通过回调告诉adapter进行移动操作。
如何支持左右滑动呢?同样是支持对应的权限

int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;

处理滑动删除事件

public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder srcViewHolder,
                      RecyclerView.ViewHolder targetViewHolder) {

    boolean result = itemTouchMoveListener.onItemMove(srcViewHolder.getAdapterPosition(),
            targetViewHolder.getAdapterPosition());
    return result;
}

接下来通过回调告诉了adapter需要操作的条目,就可以进行移动和删除对应的操作。

@Override
public boolean onItemMove(int fromPosition, int toPosition) {

    Collections.swap(contents,fromPosition,toPosition);
    notifyItemMoved(fromPosition,toPosition);
    return false;
}

@Override
public boolean onItemRemove(int position) {
    contents.remove(position);
    notifyItemRemoved(position);
    return true;
}

下面是完整的代码

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new CommonItemMoveCallback(itemMoveAdapter));
itemTouchHelper.attachToRecyclerView(recyclerView);
public class CommonItemMoveCallback extends ItemTouchHelper.Callback {

    private ItemTouchMoveListener itemTouchMoveListener;

    public CommonItemMoveCallback(ItemTouchMoveListener itemTouchMoveListener) {
        this.itemTouchMoveListener = itemTouchMoveListener;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        int result = makeMovementFlags(dragFlags, swipeFlags);
        return result;
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder srcViewHolder,
                          RecyclerView.ViewHolder targetViewHolder) {

        boolean result = itemTouchMoveListener.onItemMove(srcViewHolder.getAdapterPosition(),
                targetViewHolder.getAdapterPosition());
        return result;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        itemTouchMoveListener.onItemRemove(viewHolder.getAdapterPosition());
    }

    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

    /**
     *
     * @param viewHolder
     * @param actionState
     */
    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        super.onSelectedChanged(viewHolder, actionState);
    }

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
    }

    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
}

后面有三个方法,可以实现点击拖拽滑动时更改背景颜色,以及滑动到固定位置,实现类似QQ侧滑删除效果。 后续更新出来

发布了58 篇原创文章 · 获赞 16 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/dingshuhong_/article/details/82690883