我想要实现的目标是:使用GridLayoutManager创建一个RecyclerView,支持拖放并在拖动时重新排列项。
附注:第一次开发拖放功能。
有很多关于如何使用ListView实现此功能的主题,例如:https://raw.githubusercontent.com/btownrippleman/FurthestProgress/master/FurthestProgress/src/com/anappforthat/android/languagelineup/DynamicListView.java。
然而,这些示例通常需要大量代码,并且会创建拖动视图的位图。因为RecyclerView提供了重新排列动画,所以似乎应该能够使用
因此,我进行了一些尝试并得出了以下结论:
附注:第一次开发拖放功能。
有很多关于如何使用ListView实现此功能的主题,例如:https://raw.githubusercontent.com/btownrippleman/FurthestProgress/master/FurthestProgress/src/com/anappforthat/android/languagelineup/DynamicListView.java。
然而,这些示例通常需要大量代码,并且会创建拖动视图的位图。因为RecyclerView提供了重新排列动画,所以似乎应该能够使用
View.startDrag(...)
和RecyclerView来实现相同的结果,使用notifyItemAdded()
,notifyItemMoved()
和notifyItemRemoved()
进行操作。因此,我进行了一些尝试并得出了以下结论:
final CardAdapter adapter = new CardAdapter(list);
adapter.setHasStableIds(true);
adapter.setListener(new CardAdapter.OnLongClickListener() {
@Override
public void onLongClick(View view) {
ClipData data = ClipData.newPlainText("","");
View.DragShadowBuilder builder = new View.DragShadowBuilder(view);
final int pos = mRecyclerView.getChildAdapterPosition(view);
final Goal item = list.remove(pos);
mRecyclerView.setOnDragListener(new View.OnDragListener() {
int prevPos = pos;
@Override
public boolean onDrag(View view, DragEvent dragEvent) {
final int action = dragEvent.getAction();
switch(action) {
case DragEvent.ACTION_DRAG_LOCATION:
View onTopOf = mRecyclerView.findChildViewUnder(dragEvent.getX(), dragEvent.getY());
int i = mRecyclerView.getChildAdapterPosition(onTopOf);
list.add(i, list.remove(prevPos));
adapter.notifyItemMoved(prevPos, i);
prevPos = i;
break;
case DragEvent.ACTION_DROP:
View underView = mRecyclerView.findChildViewUnder(dragEvent.getX(), dragEvent.getY());
int underPos = mRecyclerView.getChildAdapterPosition(underView);
list.add(underPos, item);
adapter.notifyItemInserted(underPos);
adapter.notifyDataSetChanged();
break;
}
return true;
}
});
view.startDrag(data, builder, view, 0);
}
});
mRecyclerView.setAdapter(adapter);
这段代码有点起作用,我明白交换的部分,但非常不稳定/抖动,并且有时在刷新时整个网格会重新排列回原始顺序或某些随机顺序。无论如何,上面的代码只是我第一次快速尝试,我更感兴趣的是是否有一种标准/最佳实践方法来使用ReyclerView进行拖放,或者解决它的正确方式是否仍然与多年来用于ListViews的方式相同?
val item = items.removeAt(fromPosition) items.add(toPosition, item) recyclerView.adapter!!.notifyItemMoved(fromPosition, toPosition)
。 - android developer