【Android】RecycleView 拖拽功能踩坑记录

1. RecycleView 的拖拽不是简单的集合数据交换, 是移动.

单纯以为  RecycleView 的拖拽和集合数据交换两个概念一样的做法:
// 犯了一个很严重的错误,单纯的以为拖拽就是两个位置相互交换,实际上不是这样的
Collections.swap(mDataList, beforePosition, afterPosition);
mAdapter.notifyItemMoved(beforePosition, afterPosition);

其实不是这样的, 例子如下:
移动之前的列表
1 2 3 4 5
6 7
使用 Collections.swap(mDataList, 0, 6);交换后是这样的(将 1和7 交换)
7 2 3 4 5
6 1
但是使用notifyItemMoved(0, 6), 却是这样的:
2 3 4 5 6
7 1
因此我们的数据集更新的步伐应该与 RecycleView 的拖拽的步伐一致
正确的操作应该是这样的:

    /**
     * 移动数据条目的位置
     *
     * @param fromPosition 原位置
     * @param toPosition   目标位置
     */
    public void moveItem(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            //交换时,确保数据position不错乱,从上往下拖动,每滑动一个item,都将list中的item向下交换,向上滑同理。
            //交换数据源两个数据的位置
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(getData(), i, i + 1);
            }
        } else {
            //交换数据源两个数据的位置
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(getData(), i, i - 1);
            }
        }
        notifyItemMoved(fromPosition, toPosition);
    }

2. 移动之后, 点击移动之后item,点击事件错乱, 是因为的position获取错了

正常我们使用的positionpublic void onBindViewHolder(@NonNull ImageListViewHolder holder, int position) 中的 position. 然而, 当发证拖拽事件之后, 并不会重新调用 onBindViewHolder(ImageListViewHolder holder, int position)这个方法. 即你原先使用的position, 不会被更新。 导致点击事件出错。正确的做法使用:
holder.getLayoutPosition() 或者 holder.getAdapterPosition() 获取最新的position

你可能感兴趣的:(【Android】RecycleView 拖拽功能踩坑记录)