Recyclerview条目可拖拽可侧滑删除实战详解

  • 先看效果图

    这里写图片描述

    要实现这种效果,Android提供的有相关Api:ItemTouchHelper, 它是继承ItemDecoration的, 它内部有一个静态的抽象类

 public abstract static class Callback 
  • 首先我们需要准备一个recyclerview的列表数据

[下面开始正文]

  • 我们需要重写ItemTouchHelper.Callback这个抽个抽象类,并需要重写三个方法:
    • getMovementFlags : 主要通过这个方法,我们能拿到一个方向
    • onMove:拖动时回调这个函数
    • onSwiped : 侧滑回调这个函数
public class WolfItemTouchHelperCallback extends Callback{
     @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

        return 0;
    } 
     @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {

        return true;
    }
     @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

    }
    }

问题来了我们怎么知道它根据什么知道长按拖动还是侧滑删除呢?
所以我们还需要两个辅助方法用来判断是拖动还是侧滑:isLongPressDragEnabledisItemViewSwipeEnabled()
在这个ItemTouchHelper.Callback静态抽象内部类中有这两个方法

 /**
     * 可拖动返回true
     * */
    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

    /**
     * 可侧滑返回true
     * */
    @Override
    public boolean isItemViewSwipeEnabled() {
        return true;
    }
  • ItemTouchHelper.Callback与Adapter进行通信
    目的是要adapter时刻知道列表发生了变化,以便及时刷新ui界面

这里我们定义一个接口进行通信,我们需要当ui界面发生拖动和侧滑事件后,把位置的变化信息传递给接口。然后adapter实现这个接口,就可以从里面获取位置信息了,这样就可以及时刷新ui界面了!

//定义的接口
public interface ItemHelper {
    //拖动
    void onItemMove(int frompos,int topos);
    //侧滑
    void onItemDimss(int topos);
}

看完整WolfItemTouchHelperCallback.java

public class WolfItemTouchHelperCallback extends ItemTouchHelper.Callback {

    /**
     * 第一步重写这三个方法
     * getMovementFlags
     * onMove
     * onSwiped
     * 第二步重写这三个方法后我们还需要两个帮助函数
     * isLongPressDragEnabled 和
     * isItemViewSwipeEnabled
     * 第三步自定义接口作为WolfItemTouchHelperCallback和Adapter通信的桥梁,在构造方法中声明这个接口
     *
     * */
    private ItemHelper itemHelper;
    public WolfItemTouchHelperCallback(ItemHelper itemHelper){
        this.itemHelper=itemHelper;
    }

    /**
     * 获取一个方向
     * */
    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    //up  down  既能向上拖拽也能向下拖拽
        int up_down_drags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipes  = ItemTouchHelper.START | ItemTouchHelper.END;
        Log.e("getMovementFlags","getMovementFlags");
        return makeMovementFlags(up_down_drags,swipes);
    }

    /**
     * 拖动时调用
     * */
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        /**
         * 这个函数在拖动时调用
         * 我们在拖动时,需要把拖动item的起始position,和要拖到到的位置的position,通知给adapter,让其刷新view
         * 我们可以通过自定义接口来传递数据
         * */
        int adapterFrom_Position = viewHolder.getAdapterPosition();
        int adapterTo_Position = target.getAdapterPosition();
        Log.e("onMove","onMove");
        //这里把位置信息传递给接口了     
           itemHelper.onItemMove(adapterFrom_Position,adapterTo_Position);  
        return true;
    }

    /**
     * 侧滑时调用
     * */
    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        int adapterPosition = viewHolder.getAdapterPosition();
         Log.e("onSwiped","onSwiped");
        itemHelper.onItemDimss(adapterPosition);

    }


    /**
     * 可拖动返回true
     * */
    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

    /**
     * 可侧滑返回true
     * */
    @Override
    public boolean isItemViewSwipeEnabled() {
        return true;
    }

}

看完整WolfRecAdapter.java

public class WolfRecAdapter extends RecyclerView.Adapter<WolfRecAdapter.ViewHolder> implements ItemHelper{

    public Context mCpntext;
    public List mList;
    private final LayoutInflater inflater;

    public WolfRecAdapter(Context mCpntext, List mList){
        this.mCpntext=mCpntext;
        this.mList=mList;
        inflater = LayoutInflater.from(mCpntext);


    }


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
      Log.e("position","position"+position);
        holder.tv.setText(mList.get(position)+"");

    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    /**
     * 拖拽时
     * */
    @Override
    public void onItemMove(int frompos, int topos) {
        Object remove = mList.remove(frompos);
        mList.add(topos > frompos ? topos - 1 : topos, remove);
        Log.e("onItemMove","onItemMove");
        //刷新view
        notifyItemMoved(frompos,topos);
    }

    /**
     * 侧滑
     * */
    @Override
    public void onItemDimss(int topos) {
        mList.remove(topos);
        Log.e("onItemDimss","onItemDimss");
        //移除
        notifyItemRemoved(topos);

    }

    public class ViewHolder extends RecyclerView.ViewHolder{

        private final TextView tv;

        public ViewHolder(View itemView) {
            super(itemView);
            tv = (TextView) itemView.findViewById(R.id.tv);
        }
    }
}
  • 最后在activity中的使用
//在设置玩适配器后可以这样写

//把adapter自定义的WolfItemTouchHelperCallback
ItemTouchHelper.Callback callback = new WolfItemTouchHelperCallback(wolfRecAdapter);
//把自定义的WolfItemTouchHelperCallback  传入到ItemTouchHelper
ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(recyclerView);

到这里已经实现了可拖动可侧滑删除的功能了!

  • 我们通过Log进一步分析下

    • 我们打开app,不做任何操作,在当前界面显示的条目:
      这里写图片描述

    • 拖拽时:把第二个条目(position1)拖到第一个条目的位置(position0)
      这里写图片描述
      我们可以发现当我们触目条目时会调用getMovementFlags,确定是长按拖动时会依次调用:isLongPressDragEnabled-getMovementFlags-onMove-onItemMove(自定义的接口)

    • 侧滑删除时:
      这里写图片描述
      之所以多次调用isItemViewSwipeEnabled是因为,只要我们滑动列表就会多次调用,我们点击时很难准确的点到一个点。getMovementFlags-onSwiped-onItemDimss。position也会发生变化,因为删除一个后面的肯定要补充一个位置。

通过这些log我们很明确的看到他的调用流程了!

Activity-WolfItemTouchHelperCallback-WolfRecAdapter刷新界面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值