ItemTouchHelper.SimpleCallback onMove() 未触发
ItemTouchHelper.SimpleCallback onMove() is not triggered
我想在我的RecyclerView
中实现拖放。正如我发现的那样,实现这一点的最佳方法是将 ItemTouchHelper
附加到 RecyclerView
.
onSwiped()
工作正常,但从未触发 onMove()
。
我就是这样做的:
EditIngredientsRecyclerViewAdapter premixableIngredientsAdapter = new EditIngredientsRecyclerViewAdapter(this, typeOfComponents);
GridLayoutManager gridLayoutManager1 = new GridLayoutManager(getContext(), 1);
recyclerView.setAdapter(premixableIngredientsAdapter);
recyclerView.setLayoutManager(gridLayoutManager1);
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
Log.d(TAG, "onMove: ");
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
Log.d(TAG, "onSwiped: ");
}
};
ItemTouchHelper touchHelper = new ItemTouchHelper(simpleItemTouchCallback);
touchHelper.attachToRecyclerView(recyclerView);
对不起,我没有足够的声誉在问题下发表评论。尝试将 return false
更改为 return true
我忘记了两件事:
**1。将 SimpleCallback
更新为:
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
// Notify Adapter of the moved item!
recyclerView.getAdapter().notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
// No swipe action
}
@Override
public boolean isItemViewSwipeEnabled() {
// Disable swipe (dont override this method or return true, if you want to have swipe)
return false;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// Set movement flags to specify the movement direction
// final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT; <-- for all directions
// In this case only up and down is allowed
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
}
};
特别重要的是覆盖getMovementFlags()
指定拖拽的方向并通知adapter移动的Item,我在onMove()
2。 itemTouchHelper.startDrag(viewHolderElement)
触发拖动:
我通过在 RecyclerViewAdapter 中创建一个小界面来做到这一点:
public interface OnStartDragListener {
void onStartDrag(RecyclerView.ViewHolder holder);
}
创建适配器时,像这样传入一个新的 OnStartDragListenerElement:
EditIngredientsRecyclerViewAdapter premixableIngredientsAdapter = new EditIngredientsRecyclerViewAdapter(this, typeOfComponents, new EditIngredientsRecyclerViewAdapter.OnStartDragListener() {
@Override
public void onStartDrag(RecyclerView.ViewHolder holder) {
touchHelper.startDrag(holder);
Log.d(TAG, "onStartDrag: ");
}
});
并在 Touchlistener 中调用 onStartDrag(viewHolder)
,在视图中放置一个按钮,如下所示:
holder.itemBinding.dragBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mOnStartDragListener.onStartDrag(holder);
return false;
}
});
我相信,还有更有效的实现,一旦有人在这里发布,我会接受。但是,这至少使它对我有用。
我列出了 ItemTouchHelper.SimpleCallback 和 ItemTouchHelper.Callback() 的代码。代码中列出了注释,以帮助分解正在发生的事情。
ItemTouchHelper.SimpleCallback
在 RecyclerView 实现下的 Activity/Fragment 创建一个 ItemTouchHelper.SimpleCallback 对象。您需要覆盖 onMove() 和 onSwiped() 方法。
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
ItemTouchHelper.RIGHT or ItemTouchHelper.LEFT
) {
// You'll need to Override
override fun onMove(
recyclerView: RecyclerView,
viewHolder: ViewHolder,
target: ViewHolder
): Boolean {
// Get the position start position of the item
val startPosition = viewHolder.adapterPosition
// Get the endPosition, where you draged it to.
val endPosition = target.adapterPosition
// Submit start and end position to notifyItemMoved.
recyclerView.adapter?.notifyItemMoved(startPosition, endPosition)
// true if moved, false otherwise
return true
}
override fun onSwiped ...
如果您想创建 CustomItemTouchCallback
创建一个扩展 ItemTouchHelper.Callback() 的 customItemTouchHelper class,您需要覆盖 getMovementFlags()、onMove() 和 onSwiped()
class CustomItemTouchHelper(mContext: Context, val viewModel: MyViewModel) : ItemTouchHelper.Callback() {
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
val swipeFlags = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
return makeMovementFlags(dragFlags, swipeFlags)
}
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val startPosition = viewHolder.adapterPosition
val endPosition = target.adapterPosition
recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
// true if moved, false otherwise
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val editList: MutableList<User>? = viewModel.usersList?.value as MutableList<User>?
val editListCopy = editList?.toMutableList()
editListCopy?.removeAt(viewHolder.adapterPosition)
viewModel.usersList?.postValue(editListCopy)
}
override fun isItemViewSwipeEnabled(): Boolean {
// Allows items to be swiped left or right.
return true
}
override fun isLongPressDragEnabled(): Boolean {
// Allows for long click so items can be dragged, moved up or down in the list.
return true
}
}
现在,在您的 Activity 或 Fragment 中,您需要创建一个 CustomItemHelper 对象,然后将 RecyclerView 附加到它。
val rv = findViewById<RecyclerView>(R.id.recycler_view)
rv.apply {
...
val customItemTouchHelper = ItemTouchHelper(CustomItemTouchHelper(context, viewModel))
customItemTouchHelper.attachToRecyclerView(rv)
}
您的 ItemTouchHelper.SimpleCallback
应该在构造函数中设置移动标志并且 onMove 方法应该 return true
.
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.LEFT;
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(moveFlags, swipeFlags) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
Log.d(TAG, "onMove: ");
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
// Swap list items in adapter...
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
Log.d(TAG, "onSwiped: ");
}
}
我想在我的RecyclerView
中实现拖放。正如我发现的那样,实现这一点的最佳方法是将 ItemTouchHelper
附加到 RecyclerView
.
onSwiped()
工作正常,但从未触发 onMove()
。
我就是这样做的:
EditIngredientsRecyclerViewAdapter premixableIngredientsAdapter = new EditIngredientsRecyclerViewAdapter(this, typeOfComponents);
GridLayoutManager gridLayoutManager1 = new GridLayoutManager(getContext(), 1);
recyclerView.setAdapter(premixableIngredientsAdapter);
recyclerView.setLayoutManager(gridLayoutManager1);
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
Log.d(TAG, "onMove: ");
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
Log.d(TAG, "onSwiped: ");
}
};
ItemTouchHelper touchHelper = new ItemTouchHelper(simpleItemTouchCallback);
touchHelper.attachToRecyclerView(recyclerView);
对不起,我没有足够的声誉在问题下发表评论。尝试将 return false
更改为 return true
我忘记了两件事:
**1。将 SimpleCallback
更新为:
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
// Notify Adapter of the moved item!
recyclerView.getAdapter().notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
// No swipe action
}
@Override
public boolean isItemViewSwipeEnabled() {
// Disable swipe (dont override this method or return true, if you want to have swipe)
return false;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// Set movement flags to specify the movement direction
// final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT; <-- for all directions
// In this case only up and down is allowed
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
}
};
特别重要的是覆盖getMovementFlags()
指定拖拽的方向并通知adapter移动的Item,我在onMove()
2。 itemTouchHelper.startDrag(viewHolderElement)
触发拖动:
我通过在 RecyclerViewAdapter 中创建一个小界面来做到这一点:
public interface OnStartDragListener {
void onStartDrag(RecyclerView.ViewHolder holder);
}
创建适配器时,像这样传入一个新的 OnStartDragListenerElement:
EditIngredientsRecyclerViewAdapter premixableIngredientsAdapter = new EditIngredientsRecyclerViewAdapter(this, typeOfComponents, new EditIngredientsRecyclerViewAdapter.OnStartDragListener() {
@Override
public void onStartDrag(RecyclerView.ViewHolder holder) {
touchHelper.startDrag(holder);
Log.d(TAG, "onStartDrag: ");
}
});
并在 Touchlistener 中调用 onStartDrag(viewHolder)
,在视图中放置一个按钮,如下所示:
holder.itemBinding.dragBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mOnStartDragListener.onStartDrag(holder);
return false;
}
});
我相信,还有更有效的实现,一旦有人在这里发布,我会接受。但是,这至少使它对我有用。
我列出了 ItemTouchHelper.SimpleCallback 和 ItemTouchHelper.Callback() 的代码。代码中列出了注释,以帮助分解正在发生的事情。
ItemTouchHelper.SimpleCallback 在 RecyclerView 实现下的 Activity/Fragment 创建一个 ItemTouchHelper.SimpleCallback 对象。您需要覆盖 onMove() 和 onSwiped() 方法。
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
ItemTouchHelper.RIGHT or ItemTouchHelper.LEFT
) {
// You'll need to Override
override fun onMove(
recyclerView: RecyclerView,
viewHolder: ViewHolder,
target: ViewHolder
): Boolean {
// Get the position start position of the item
val startPosition = viewHolder.adapterPosition
// Get the endPosition, where you draged it to.
val endPosition = target.adapterPosition
// Submit start and end position to notifyItemMoved.
recyclerView.adapter?.notifyItemMoved(startPosition, endPosition)
// true if moved, false otherwise
return true
}
override fun onSwiped ...
如果您想创建 CustomItemTouchCallback
创建一个扩展 ItemTouchHelper.Callback() 的 customItemTouchHelper class,您需要覆盖 getMovementFlags()、onMove() 和 onSwiped()
class CustomItemTouchHelper(mContext: Context, val viewModel: MyViewModel) : ItemTouchHelper.Callback() {
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
val swipeFlags = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
return makeMovementFlags(dragFlags, swipeFlags)
}
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val startPosition = viewHolder.adapterPosition
val endPosition = target.adapterPosition
recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
// true if moved, false otherwise
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val editList: MutableList<User>? = viewModel.usersList?.value as MutableList<User>?
val editListCopy = editList?.toMutableList()
editListCopy?.removeAt(viewHolder.adapterPosition)
viewModel.usersList?.postValue(editListCopy)
}
override fun isItemViewSwipeEnabled(): Boolean {
// Allows items to be swiped left or right.
return true
}
override fun isLongPressDragEnabled(): Boolean {
// Allows for long click so items can be dragged, moved up or down in the list.
return true
}
}
现在,在您的 Activity 或 Fragment 中,您需要创建一个 CustomItemHelper 对象,然后将 RecyclerView 附加到它。
val rv = findViewById<RecyclerView>(R.id.recycler_view)
rv.apply {
...
val customItemTouchHelper = ItemTouchHelper(CustomItemTouchHelper(context, viewModel))
customItemTouchHelper.attachToRecyclerView(rv)
}
您的 ItemTouchHelper.SimpleCallback
应该在构造函数中设置移动标志并且 onMove 方法应该 return true
.
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.LEFT;
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(moveFlags, swipeFlags) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
Log.d(TAG, "onMove: ");
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
// Swap list items in adapter...
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
Log.d(TAG, "onSwiped: ");
}
}