欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

RecyclerView 使用ItemTouchHelper类实现拖拽排序

程序员文章站 2022-05-15 19:30:01
...

记得以前还没有RecyclerView的时候,做拖拽排序很麻烦,而现在因为RecyclerView的诞生,很多复杂的操作都可以完美实现了,例如轮播、流式布局等等。

先写一个简单的RecyclerView例子,然后慢慢拓展吧。

public class MoveItemActivity extends AppCompatActivity {
    private RecyclerView rl;
    private MyAdapter adapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_coo4);
        initRecycler();
    }

    private void initRecycler() {
        rl = findViewById(R.id.rv_content);
        rl.setLayoutManager(new LinearLayoutManager(this));
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            list.add("这是模拟数据" + i);
        }
        rl.setAdapter(adapter = new MyAdapter(list));
    }


    public class MyAdapter extends RecyclerView.Adapter<Holder> implements ItemTouchMoveListener {
        List<String> list;


        public MyAdapter(List<String> list) {
            this.list = list;
        }

        @NonNull
        @Override
        public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler_main, parent, false);
            Holder holder = new Holder(inflate);
            holder.name = inflate.findViewById(R.id.tv_name);
            holder.image = inflate.findViewById(R.id.iv_image);
            return holder;
        }

        @Override
        public void onBindViewHolder(@NonNull Holder holder, int position) {
            holder.name.setText(list.get(position));
        }

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


    class Holder extends RecyclerView.ViewHolder {
        public TextView name;
        public View image;

        public Holder(@NonNull View itemView) {
            super(itemView);
        }
    }
}

运行截图:

RecyclerView 使用ItemTouchHelper类实现拖拽排序

使用v7包提供的ItemTouchHelper类处理Item的拖拽事件:

  • 1.默认构造:
    /**
     * 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;
    }
  • 2.可以看到构造需要一个Callback,所以我们写个类进行实现:
public class ItemTouchCallback extends ItemTouchHelper.Callback {


    /**
     * 判断动作方向
     */
    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        int flags = makeMovementFlags(dragFlags, swipeFlags);
        return flags;
    }

    /**
     * 拖拽回调
     */
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        if (viewHolder.getItemViewType() != target.getItemViewType()) {
            return false;
        }
        return true;
    }

    /**
     * 侧滑回调
     */
    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

    }

    /**
     * 长按拖拽开关 
     *
     * @return 代表是否开启长按拖拽
     */
    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }
}
  • 3.将监听与RecyclerView进行绑定:
new ItemTouchHelper(new ItemTouchCallback()).attachToRecyclerView(rl); 
  • 4.此时RecyclerView已经可以拖动排序了,但是这里还有一个坑,UI因为拖动改变了顺序,而我们真实的数据还是原来的顺序,所以我们还需要在onMove方法中写一个监听,或者将adapter的数据传到ItemTouchCallback类,进行位置交换操作,例如:
    /**
     * 拖拽回调
     */
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        if (viewHolder.getItemViewType() != target.getItemViewType()) {
            return false;
        }
        //将我们的真实(List)数据位置交换
        moveListener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

gif预览:

RecyclerView 使用ItemTouchHelper类实现拖拽排序