From 7b5c49a5b36f57795fce3c4f24155a66add19a19 Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Mon, 7 Mar 2022 08:29:58 -0700 Subject: [PATCH] ui: disable default actions in drag helpers Disable the default long-press action in the ItemTouchHelper usages. ItemTouchHelper provides a long-press action to start an item drag by default. However, because Auxio adds a drag handle on top of this action, this actually results in a conflict with the default behavior in certain cases. Replace it with a custom version of the long-press action within the viewholders themselves. --- CHANGELOG.md | 2 ++ .../main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt | 7 ++++++- .../java/org/oxycblt/auxio/home/tabs/TabDragCallback.kt | 5 +++++ .../java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt | 7 ++++++- .../org/oxycblt/auxio/playback/queue/QueueDragCallback.kt | 4 +++- .../java/org/oxycblt/auxio/playback/queue/QueueFragment.kt | 6 ++---- 6 files changed, 24 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 090ed95e3..8ee81b9a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ from the system theme was used [#80] - Fixed years deliberately set as "0" showing up as "No Date" - Fixed headset management unexpectedly starting audio when the app initially opens - Fixed crash that would occur during a playback restore with specific queue states [#89] +- Partially fixed buggy behavior when multiple queue items were dragged in quick +succession #### What's Changed - All cover art is now cropped to a 1:1 aspect ratio diff --git a/app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt index 636cf5e38..401663c45 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt @@ -70,14 +70,19 @@ class TabAdapter( isChecked = tab is Tab.Visible } + // Roll our own drag handlers as the default ones suck binding.tabDragHandle.setOnTouchListener { _, motionEvent -> binding.tabDragHandle.performClick() - if (motionEvent.actionMasked == MotionEvent.ACTION_DOWN) { touchHelper.startDrag(this) true } else false } + + binding.root.setOnLongClickListener { + touchHelper.startDrag(this) + true + } } } } diff --git a/app/src/main/java/org/oxycblt/auxio/home/tabs/TabDragCallback.kt b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabDragCallback.kt index 4f3942615..f9de5ac79 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/tabs/TabDragCallback.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabDragCallback.kt @@ -25,6 +25,8 @@ import androidx.recyclerview.widget.RecyclerView /** * A simple [ItemTouchHelper.Callback] that handles dragging items in the tab customization menu. * Unlike QueueAdapter's ItemTouchHelper, this one is bare and simple. + * TODO: Consider unifying the shared behavior between this and QueueDragCallback into a single + * class. */ class TabDragCallback(private val getTabs: () -> Array) : ItemTouchHelper.Callback() { private val tabs: Array get() = getTabs() @@ -70,6 +72,9 @@ class TabDragCallback(private val getTabs: () -> Array) : ItemTouchHelper.C override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {} + // We use a custom drag handle, so disable the long press action. + override fun isLongPressDragEnabled(): Boolean = false + /** * Add the tab adapter to this callback. * Done because there's a circular dependency between the two objects diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt index cfc18f848..7c362c5fb 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt @@ -142,14 +142,19 @@ class QueueAdapter( binding.songName.requestLayout() binding.songInfo.requestLayout() + // Roll our own drag handlers as the default ones suck binding.songDragHandle.setOnTouchListener { _, motionEvent -> binding.songDragHandle.performClick() - if (motionEvent.actionMasked == MotionEvent.ACTION_DOWN) { touchHelper.startDrag(this) true } else false } + + binding.body.setOnLongClickListener { + touchHelper.startDrag(this) + true + } } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt index 3478f6a9e..a010fadf8 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt @@ -128,7 +128,7 @@ class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouc // When an elevated item is cleared, we reset the elevation using another animation. val holder = viewHolder as QueueAdapter.QueueSongViewHolder - if (holder.itemView.translationZ != 0.0f) { + if (holder.itemView.translationZ != 0f) { logD("Dropping queue item") val bg = holder.bodyView.background as MaterialShapeDrawable @@ -165,6 +165,8 @@ class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouc } } + override fun isLongPressDragEnabled(): Boolean = false + /** * Add the queue adapter to this callback. * Done because there's a circular dependency between the two objects diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt index 8765c4d98..0337c54c7 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt @@ -43,15 +43,13 @@ class QueueFragment : Fragment() { savedInstanceState: Bundle? ): View { val binding = FragmentQueueBinding.inflate(inflater) - val callback = QueueDragCallback(playbackModel) - val helper = ItemTouchHelper(callback) val queueAdapter = QueueAdapter(helper) - var lastShuffle = playbackModel.isShuffling.value - callback.addQueueAdapter(queueAdapter) + var lastShuffle = playbackModel.isShuffling.value + // --- UI SETUP --- binding.lifecycleOwner = viewLifecycleOwner