如何知道用户何时完成移动RecyclerView项目?

4
我需要在用户放下一个项目时执行某些操作。ItemTouchHelper似乎只有onMove和onMoved的调用,而无论用户是否完成移动项目都会发生。 如何知道用户何时完成移动项目?即,他们已经松开手指并把项目放回到recyclerView中?
3个回答

5
你可以重写 ItemTouchHelper.Callback 类中的 onSelectedChanged() 回调方法,使用一个 switch case 语句来检查 actionState 的值(可能是 ACTION_STATE_DRAGACTION_STATE_SWIPEACTION_STATE_IDLE)。

ACTION_STATE_IDLE 是你想要的,它会在滑动/拖动操作结束且用户将手指离开屏幕时触发。

你可以使用一个布尔变量来判断是滑动还是拖动,如下所示。

private ItemTouchHelper createHelperCallback() {
    return new ItemTouchHelper(new ItemTouchHelper.Callback() {

        boolean isSwiped = false;

        @Override
        public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
            return 0;
        }

        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
            return false;
        }

        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        }

        @Override
        public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {

            switch (actionState) {

                case ItemTouchHelper.ACTION_STATE_DRAG:
                    // the user is dragging an item and didn't lift their finger off yet
                   isSwiped = false;
                   break;

                case ItemTouchHelper.ACTION_STATE_SWIPE:
                    // the user is swiping an item and didn't lift their finger off yet
                    isSwiped = true;
                    break;

                case ItemTouchHelper.ACTION_STATE_IDLE:
                    // the user just dropped the item (after dragging it), and lift their finger off.

                    if (isSwiped) // The user used onSwiped()
                        Toast.makeText(MainActivity.this, "Swiping is over", Toast.LENGTH_SHORT).show();
                        
                    else // The user used onMove()
                        Toast.makeText(MainActivity.this, "Dragging & Dropping are over", Toast.LENGTH_SHORT).show();
                    isSwiped = false;
                
            }
        }

    });
}

然后在你的RecyclerView上使用它。

createHelperCallback().attachToRecyclerView(recyclerView);

预览


原来 onClear() 是我需要让它工作的,但这个答案对我也非常有帮助,因为我也在尝试理解如何利用那些操作状态。谢谢! - Ben Mora
1
关于这个答案,有几件事情需要注意。因为你没有在onMove中更新数据,所以其他项目不会动画地腾出空间来给拖动的项目(你甚至可以在视频中看到这一点)。此外,这个答案没有跟踪_哪个项目_实际上移动到了哪里。你需要在onMove中完成这个任务。另外,在Toast之后重置isSwiped/isMoved状态,以防止多个ACTION_STATE_IDLE调用。最后,isSwiped不需要是一个布尔数组,只需要是布尔值即可。 - tir38

3

很容易,只需重写onClearView()方法:

@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {    //called when you dropped the item
    super.clearView(recyclerView, viewHolder);

    Toast.makeText(recyclerView.getContext(), "Item dropped on position: " + viewHolder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}

-1

您还可以重写getAnimationDuration(),它会在onSelectedChanged()之前调用(仅当用户的手指抬起时),但是您无法在此函数中访问viewHolder


这似乎是RV库未来版本中可能会在没有通知的情况下更改的实现细节。 - tir38

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接