Android:RecyclerView自由拖动item

原生就自带有可拖动item的工具:ItemTouchHelper

看下效果:

可拖动RecyclerView预览效果

接下来我们看如何使用。

1、自定义ItemTouchHelper的callback,用来限制是否可以拖动,以及拖动之后的位置更新:

其中判断条件中的item.isMovable这边是记录该item是否可以拖动,也可以换成其他判断条件比如根据位置判断等。

java 复制代码
private static class MyItemTouchHelperCallback extends ItemTouchHelper.Callback {

        private final ItemAdapter itemAdapter;

        public MyItemTouchHelperCallback(ItemAdapter itemAdapter) {
            this.itemAdapter= itemAdapter;
        }

        @Override
        public int getMovementFlags(@NonNull RecyclerView recyclerView,
                                    @NonNull RecyclerView.ViewHolder viewHolder) {
            int layoutPosition = viewHolder.getLayoutPosition();
            ItemInfo item = ItemAdapter.getItem(layoutPosition);
            if (!item.isMovable()) {
                //不可拖动
                return makeMovementFlags(0, 0);
            }
            //这里表示可以拖动的方向,比如如果不给往上方拖动则去掉ItemTouchHelper.UP
            final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN
                    | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
            return makeFlag(ItemTouchHelper.ACTION_STATE_DRAG, dragFlags);
        }

        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView,
                              @NonNull RecyclerView.ViewHolder viewHolderSource,
                              @NonNull RecyclerView.ViewHolder viewHolderTarget) {
            int layoutPosition = viewHolderTarget.getLayoutPosition();
            ItemInfo item = itemAdapter.getItem(layoutPosition);
            if (!item.isMovable()) {
                //不可拖动到这里
                return false;
            }
            itemAdapter.onMove(viewHolderSource.getAdapterPosition(),
                    viewHolderTarget.getAdapterPosition());
            return true;
        }

        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {

        }

    }

2、在适配器提供获取item信息和移动之后更新数据的方法给到这个callback使用:

java 复制代码
    public ItemInfo getItem(int position) {
        if (position >= 0 && position < mList.size()) {
            return mList.get(position);
        }
        return null;
    }

    public void onMove(int sourcePosition, int targetPosition) {
        ItemInfo item = mList.get(sourcePosition);
        mList.remove(sourcePosition);
        mList.add(targetPosition, item);
        notifyItemMoved(sourcePosition, targetPosition);
    }

3、使用这个callback类:

java 复制代码
    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(
                new MyItemTouchHelperCallback(adapter));
    itemTouchHelper.attachToRecyclerView(recyclerView);

就可以了,简简单单,轻轻松松。

另外,需要留意一点,如果你是在onBindViewHolder中有设置点击事件的,在onClickListener里面不要直接使用onBindViewHolder方法传进来的position,因为在item位置移动之后,这个position是不会变的,注册事件监听的时候这个值就跟你的点击事件绑死了,所以需要动态获取这个position:

java 复制代码
    holder.view.setOnClickListener(v -> {
        int currentPosition = holder.getAdapterPosition();
        ItemInfo info = getItem(currentPosition);
        if (listener != null) {
            listener.onItemClick(currentPosition, info);
        }
    });
相关推荐
后端码匠5 小时前
MySQL 8.0安装(压缩包方式)
android·mysql·adb
梓仁沐白6 小时前
Android清单文件
android
董可伦9 小时前
Dinky 安装部署并配置提交 Flink Yarn 任务
android·adb·flink
每次的天空9 小时前
Android学习总结之Glide自定义三级缓存(面试篇)
android·学习·glide
恋猫de小郭10 小时前
如何查看项目是否支持最新 Android 16K Page Size 一文汇总
android·开发语言·javascript·kotlin
flying robot11 小时前
小结:Android系统架构
android·系统架构
xiaogai_gai11 小时前
有效的聚水潭数据集成到MySQL案例
android·数据库·mysql
鹅鹅鹅呢12 小时前
mysql 登录报错:ERROR 1045(28000):Access denied for user ‘root‘@‘localhost‘ (using password Yes)
android·数据库·mysql
在人间负债^12 小时前
假装自己是个小白 ---- 重新认识MySQL
android·数据库·mysql
Unity官方开发者社区12 小时前
Android App View——团结引擎车机版实现安卓应用原生嵌入 3D 开发场景
android·3d·团结引擎1.5·团结引擎车机版