Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drag & drop - animation is broken #1045

Open
1 task done
MFlisar opened this issue Nov 30, 2022 · 1 comment
Open
1 task done

Drag & drop - animation is broken #1045

MFlisar opened this issue Nov 30, 2022 · 1 comment

Comments

@MFlisar
Copy link
Contributor

MFlisar commented Nov 30, 2022

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
@mikepenz
Copy link
Owner

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants