【问题标题】:ItemTouchHelper.SimpleCallback onMove() is not triggeredItemTouchHelper.SimpleCallback onMove() 未触发
【发布时间】:2020-10-06 09:27:55
【问题描述】:

我想在我的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);

【问题讨论】:

    标签: android android-recyclerview itemtouchhelper


    【解决方案1】:

    我列出了 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 类,您需要覆盖 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)
    
            }
    

    【讨论】:

    • 感谢您的回答,但由于我使用 Java 编程,而您的回答是在 Kotlin 中,我不习惯,所以我很难测试
    【解决方案2】:

    我忘记了两件事:

    **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()以指定拖动方向并通知适配器移动的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;
                    }
                });
    

    我敢肯定,有更有效的实现,一旦有人在这里发布,我会接受它。但是,这至少使它对我有用。

    【讨论】:

      【解决方案3】:

      抱歉,我没有足够的声誉来评论这个问题。尝试将return false 更改为return true

      【讨论】:

      • 没有改变任何东西。物品只是不动
      【解决方案4】:

      您的ItemTouchHelper.SimpleCallback 应该在构造函数中设置移动标志并且onMove 方法应该返回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: ");
                  }
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-26
        • 2020-11-26
        相关资源
        最近更新 更多