mikepenz/FastAdapter

Drag & drop - animation is broken

MFlisar opened this issue · 1 comments

About this issue

I see the same issue like in the video here: #991 and I do use stable ids in my adapter...

What I see is following

  • I start a drag
  • I stop it => itemTouchDropped is called followed by itemTouchStopDrag (which seems to be intended, although it seems wrong imho)
  • I update my data in itemTouchDropped => this triggers a data update and updates the adapter data which may happen during a running animation...

Problem

  • itemTouchStopDrag stops the drag animation, this means the item appears at its original position again although the back animation move animation is still running
  • ghost views as in the mentioned other issues video

Work around

I delay the the drop data update until the itemTouchStopDrag is called after a drop.

Here's my code:

private val dragCallback = SimpleDragCallback(object : ItemTouchCallback {

        var updatedItems: List<IDataItem>? = null

        override fun itemTouchOnMove(oldPosition: Int, newPosition: Int): Boolean {
            DragDropUtil.onMove(itemAdapter, oldPosition, newPosition)  // change position
            return true
        }

        override fun itemTouchDropped(oldPosition: Int, newPosition: Int) {
            L.d { "Dropped: $oldPosition => $newPosition" }
            if (oldPosition == newPosition) {
                // drag drop to same position starts the selection mode
                select(activity, oldPosition)
            } else {
                val items = itemAdapter.adapterItems.map { it.data }
                items.forEachIndexed { index, item ->
                    item.order = index
                }
                updatedItems = items
            }
        }

        override fun itemTouchStartDrag(viewHolder: RecyclerView.ViewHolder) {
            L.d { "Drag start..." }
        }

        override fun itemTouchStopDrag(viewHolder: RecyclerView.ViewHolder) {
            L.d { "Drag stop..." }
            updatedItems?.let {
                GlobalScope.launch(Dispatchers.IO) {
                    DataManager.update(it)
                }
            }
            updatedItems = null
        }
    }).apply {
        notifyAllDrops = true
        isDragEnabled = true
    }

Question

What's the reason to not delay the itemTouchDropped until after itemTouchStopDrag? This seems unlogical to me...

Details

  •  Used library version 5.7.0

Unfortunately, I currently do not have the capacity to look into this problem.

This sounds like it may be a problem, however, this would also lead to behavior changes for all usecases (given the different firing)

It may be worth to adjust this behavior in a future version. Happy to look into a PR, if you'd like to contribute these changes