6

I am using “drag & drop” and “swipe-to-dismiss” in RecyclerView with ItemTouchHelper. Without any library, according to this tutorial . It works perfectly. But the problem occurs when there is scroll in RecyclerView . When I start to drag first item down, first and second elements swap positions, RecyclerView is scrolled up and the first element(that I am dragging) occurs on bottom before last element(many swipes occure because of RecyclerView scrolling). It happens very fast, so I cannot put first element wherever I want.

Note that It happens only with first element, also only when dragging down.

I think this happens because when second element goes to position 1, third element goes to second position and also swipes with first element, and the same with other elements, they are all swiped with first element. How can I fix this.

This is what is called when first item changes position with second (and also with any dragging when items swap positions). After one swap, one item goes done:

    @Override
    public void onItemMove(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(categories, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(categories, i, i - 1);
            }
        }

        notifyItemMoved(fromPosition, toPosition);
    }
Cœur
  • 37,241
  • 25
  • 195
  • 267
Misha Akopov
  • 12,241
  • 27
  • 68
  • 82

2 Answers2

3

I had a same problem with that tutorial. I searched about that problem and got the answer finally in this link. For me, second answer worked perfectly. I will upload the code which just connects the tutorial code and the second answer code on the link.

In the Adapter

    @Override
    public void onItemMove(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(categories, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(categories, i, i - 1);
            }
        }

        // AdapterInteractionListener
        mListener.maintainRecyclerViewPosition(fromPosition, toPosition);
    }

In the Activity/Fragment

    LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
    int firstPos = layoutManager.findFirstCompletelyVisibleItemPosition();
    int offsetTop = 0;
    if(firstPos >= 0){
      View firstView = layoutManager.findViewByPosition(firstPos);
      offsetTop = layoutManager.getDecoratedTop(firstView) - layoutManager.getTopDecorationHeight(firstView);
    }

    mItemAdapter.notifyItemMoved(fromPosition, toPosition);
    if(firstPos >= 0) {
      layoutManager.scrollToPositionWithOffset(firstPos, offsetTop);
    }
forceson
  • 85
  • 8
3

Just return true in callback:

private val itemTouchHelper = object : ItemTouchHelper.Callback() {
        override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
            val drag = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.START or ItemTouchHelper.END
            val swipe = 0
            return makeMovementFlags(drag, swipe)
        }

        override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
            val fromPosition = viewHolder.adapterPosition
            val toPosition = target.adapterPosition

            Collections.swap(systemsAdapter?.currentSystems, fromPosition, toPosition)
            recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)

            return true
        }

        override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}

        override fun isItemViewSwipeEnabled(): Boolean {
            return true
        }

        override fun isLongPressDragEnabled(): Boolean {
            return true
        }

    }
Andrii Omelchenko
  • 13,183
  • 12
  • 43
  • 79