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