playback: fix more queue issues
Fix more issues with the queue, such as landscape edge-to-edge not working correctly and drag scroll events not resulting in the appbar lifting.
This commit is contained in:
parent
0268700fb4
commit
37a8cdccb6
7 changed files with 44 additions and 58 deletions
|
@ -32,9 +32,14 @@ import kotlin.math.sign
|
|||
/**
|
||||
* The Drag callback used by the queue recyclerview. Delivers updates to [PlaybackViewModel]
|
||||
* and [QueueAdapter] simultaneously.
|
||||
* @param onItemScroll Callback for when an item begins to scroll off-screen. Argument passed
|
||||
* is the dY value.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouchHelper.Callback() {
|
||||
class QueueDragCallback(
|
||||
private val playbackModel: PlaybackViewModel,
|
||||
private val onItemScroll: (Int) -> Unit
|
||||
) : ItemTouchHelper.Callback() {
|
||||
private lateinit var queueAdapter: QueueAdapter
|
||||
private var shouldLift = true
|
||||
|
||||
|
@ -57,7 +62,7 @@ class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouc
|
|||
totalSize: Int,
|
||||
msSinceStartScroll: Long
|
||||
): Int {
|
||||
// Fix to make QueueFragment scroll when an item is scrolled out of bounds.
|
||||
// Fix to make QueueFragment scroll slower when an item is scrolled out of bounds.
|
||||
// Adapted from NewPipe: https://github.com/TeamNewPipe/NewPipe
|
||||
val standardSpeed = super.interpolateOutOfBoundsScroll(
|
||||
recyclerView, viewSize, viewSizeOutOfBounds, totalSize, msSinceStartScroll
|
||||
|
@ -71,7 +76,13 @@ class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouc
|
|||
)
|
||||
)
|
||||
|
||||
return clampedAbsVelocity * sign(viewSizeOutOfBounds.toDouble()).toInt()
|
||||
val result = clampedAbsVelocity * sign(viewSizeOutOfBounds.toDouble()).toInt()
|
||||
|
||||
recyclerView.post {
|
||||
onItemScroll(result)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun onMove(
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowInsets
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
|
@ -38,10 +39,8 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
|
|||
import org.oxycblt.auxio.util.isEdgeOn
|
||||
|
||||
/**
|
||||
* A [Fragment] that contains both the user queue and the next queue, with the abielity to
|
||||
* A [Fragment] that contains both the user queue and the next queue, with the ability to
|
||||
* edit them as well.
|
||||
* TODO: Edge can be improved here by turning off the landscape checks and simply padding the
|
||||
* root view on the irregular landscape mode [I think]
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class QueueFragment : Fragment() {
|
||||
|
@ -54,7 +53,17 @@ class QueueFragment : Fragment() {
|
|||
): View {
|
||||
val binding = FragmentQueueBinding.inflate(inflater)
|
||||
|
||||
val callback = QueueDragCallback(playbackModel)
|
||||
val callback = QueueDragCallback(playbackModel) { dY ->
|
||||
// By default, CoordinatorLayout is not aware of scroll events originating from
|
||||
// when an item is scrolled off-screen, so we manually add a scroll event ourselves.
|
||||
(binding.queueAppbar.layoutParams as CoordinatorLayout.LayoutParams).behavior
|
||||
?.onNestedPreScroll(
|
||||
binding.queueCoordinator, binding.queueAppbar,
|
||||
binding.queueRecycler, 0, dY,
|
||||
IntArray(2), 0
|
||||
)
|
||||
}
|
||||
|
||||
val helper = ItemTouchHelper(callback)
|
||||
val queueAdapter = QueueAdapter(helper, playbackModel)
|
||||
var lastShuffle = playbackModel.isShuffling.value
|
||||
|
@ -101,6 +110,7 @@ class QueueFragment : Fragment() {
|
|||
if (isShuffling != lastShuffle) {
|
||||
lastShuffle = isShuffling
|
||||
|
||||
binding.queueRecycler.scrollBy(0, 100)
|
||||
binding.queueRecycler.scrollToPosition(0)
|
||||
}
|
||||
}
|
||||
|
@ -112,15 +122,21 @@ class QueueFragment : Fragment() {
|
|||
if (isEdgeOn()) {
|
||||
// Account for the side navigation bar if required.
|
||||
binding.root.setOnApplyWindowInsetsListener { v, insets ->
|
||||
val right = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
insets.getInsets(WindowInsets.Type.systemBars()).right
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
val bars = insets.getInsets(WindowInsets.Type.systemBars())
|
||||
|
||||
v.updatePadding(
|
||||
left = bars.left,
|
||||
right = bars.right
|
||||
)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
insets.systemWindowInsetRight
|
||||
v.updatePadding(
|
||||
left = insets.systemWindowInsetLeft,
|
||||
right = insets.systemWindowInsetRight
|
||||
)
|
||||
}
|
||||
|
||||
v.updatePadding(right = right)
|
||||
|
||||
insets
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.oxycblt.auxio.util.queryAll
|
|||
/**
|
||||
* A SQLite database for managing the persistent playback state and queue.
|
||||
* Yes. I know Room exists. But that would needlessly bloat my app and has crippling bugs.
|
||||
* TODO: Improve the boundary between this and [PlaybackStateManager]
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class PlaybackStateDatabase(context: Context) :
|
||||
|
|
|
@ -18,14 +18,11 @@
|
|||
|
||||
package org.oxycblt.auxio.util
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Resources
|
||||
import android.os.Build
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageButton
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.AttrRes
|
||||
|
@ -142,43 +139,3 @@ fun @receiver:AttrRes Int.resolveAttr(context: Context): Int {
|
|||
* Check if edge-to-edge is on. Really a glorified version check.
|
||||
*/
|
||||
fun isEdgeOn(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1
|
||||
|
||||
/**
|
||||
* Check if we are in the "Irregular" landscape mode (e.g landscape, but nav bar is on the sides)
|
||||
* Used to disable most of edge-to-edge if that's the case, as I cant get it to work on this mode.
|
||||
* @return True if we are in the irregular landscape mode, false if not.
|
||||
*/
|
||||
fun Activity.isIrregularLandscape(): Boolean {
|
||||
return isLandscape() && !isSystemBarOnBottom(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the system bars are on the bottom.
|
||||
* @return If the system bars are on the bottom, false if no.
|
||||
*/
|
||||
private fun isSystemBarOnBottom(activity: Activity): Boolean {
|
||||
val metrics = DisplayMetrics()
|
||||
|
||||
var width: Int
|
||||
var height: Int
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
activity.windowManager.currentWindowMetrics.bounds.also {
|
||||
width = it.width()
|
||||
height = it.height()
|
||||
}
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
activity.getSystemServiceSafe(WindowManager::class).apply {
|
||||
defaultDisplay.getMetrics(metrics)
|
||||
|
||||
width = metrics.widthPixels
|
||||
height = metrics.heightPixels
|
||||
}
|
||||
}
|
||||
|
||||
val config = activity.resources.configuration
|
||||
val canMove = (width != height && config.smallestScreenWidthDp < 600)
|
||||
|
||||
return (!canMove || width < height)
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
android:name="org.oxycblt.auxio.playback.CompactPlaybackFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="8dp"
|
||||
android:elevation="@dimen/elevation_normal"
|
||||
android:background="?attr/colorSurface"
|
||||
tools:layout="@layout/fragment_compact_playback" />
|
||||
</LinearLayout>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
tools:context=".playback.queue.QueueFragment">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/queue_coordinator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
|
@ -14,8 +15,8 @@
|
|||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/queue_appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:background="?attr/colorSurface"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface"
|
||||
app:liftOnScroll="true">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
|
@ -27,7 +28,6 @@
|
|||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/queue_recycler"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
<!-- Misc -->
|
||||
<dimen name="elevation_small">2dp</dimen>
|
||||
<dimen name="elevation_normal">4dp</dimen>
|
||||
<dimen name="elevation_large">8dp</dimen>
|
||||
|
||||
<dimen name="offset_thumb">4dp</dimen>
|
||||
</resources>
|
Loading…
Reference in a new issue