ui: switch to inset-based bottom sheet content
Do not do a measure + inset method with BottomSheetContentBehavior, instead, try to re-apply window insets to adapt with the bar instead. This fixes a lot of view clipping issues that made motion transitions non-ideal and prevented a rounded playback bar. Only remaining issue is RecyclerView instances, which need to be further reworked to resolve scroll issues and edge effect problems.
This commit is contained in:
parent
913db88fde
commit
0474940ee3
7 changed files with 35 additions and 47 deletions
|
@ -2,6 +2,12 @@
|
|||
|
||||
## dev
|
||||
|
||||
#### What's Improved
|
||||
- Improved bottom sheet code to prevent clipping issues
|
||||
|
||||
#### What's Fixed
|
||||
- Fixed incorrect font being used in the queue title
|
||||
|
||||
## 2.6.0
|
||||
|
||||
#### What's New
|
||||
|
|
|
@ -22,7 +22,6 @@ import android.util.AttributeSet
|
|||
import android.view.WindowInsets
|
||||
import android.widget.FrameLayout
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.core.view.updatePadding
|
||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||
|
||||
/**
|
||||
|
@ -37,12 +36,9 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
|||
clipToPadding = false
|
||||
}
|
||||
|
||||
override fun dispatchApplyWindowInsets(insets: WindowInsets): WindowInsets {
|
||||
return onApplyWindowInsets(insets)
|
||||
}
|
||||
|
||||
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
|
||||
updatePadding(bottom = insets.systemBarInsetsCompat.bottom)
|
||||
// Save a layout by simply moving the view bounds upwards
|
||||
translationY = -insets.systemBarInsetsCompat.bottom.toFloat()
|
||||
return insets
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,10 @@ import android.util.AttributeSet
|
|||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.settings.Settings
|
||||
import org.oxycblt.auxio.ui.AuxioSheetBehavior
|
||||
import org.oxycblt.auxio.util.getDimen
|
||||
|
||||
/**
|
||||
* The coordinator layout behavior used for the playback sheet, hacking in the many fixes required
|
||||
|
@ -33,6 +36,9 @@ class PlaybackSheetBehavior<V : View>(context: Context, attributeSet: AttributeS
|
|||
AuxioSheetBehavior<V>(context, attributeSet) {
|
||||
init {
|
||||
isHideable = true
|
||||
if (Settings(context).roundMode) {
|
||||
sheetBackgroundDrawable.setCornerSize(context.getDimen(R.dimen.size_corners_medium))
|
||||
}
|
||||
}
|
||||
|
||||
// Hack around issue where the playback sheet will try to intercept nested scrolling events
|
||||
|
|
|
@ -130,7 +130,7 @@ class QueueDragCallback(private val playbackModel: QueueViewModel) : ItemTouchHe
|
|||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean =
|
||||
) =
|
||||
playbackModel.moveQueueDataItems(
|
||||
viewHolder.bindingAdapterPosition, target.bindingAdapterPosition)
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
package org.oxycblt.auxio.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
|
@ -73,12 +72,12 @@ abstract class AuxioSheetBehavior<V : View>(context: Context, attributeSet: Attr
|
|||
child.apply {
|
||||
// Sometimes the sheet background will fade out, so guard it with another
|
||||
// colorSurface drawable to prevent content overlap.
|
||||
background =
|
||||
LayerDrawable(
|
||||
arrayOf(
|
||||
ColorDrawable(
|
||||
context.getAttrColorCompat(R.attr.colorSurface).defaultColor),
|
||||
sheetBackgroundDrawable))
|
||||
val guardDrawable =
|
||||
MaterialShapeDrawable(sheetBackgroundDrawable.shapeAppearanceModel).apply {
|
||||
fillColor = context.getAttrColorCompat(R.attr.colorSurface)
|
||||
}
|
||||
|
||||
background = LayerDrawable(arrayOf(guardDrawable, sheetBackgroundDrawable))
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
// Shadows aren't disabled by default, do that.
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.view.WindowInsets
|
|||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import com.google.android.material.bottomsheet.NeoBottomSheetBehavior
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import org.oxycblt.auxio.util.coordinatorLayoutBehavior
|
||||
import org.oxycblt.auxio.util.replaceSystemBarInsetsCompat
|
||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||
|
@ -62,15 +63,7 @@ class BottomSheetContentBehavior<V : View>(context: Context, attributeSet: Attri
|
|||
|
||||
if (consumed != lastConsumed) {
|
||||
lastConsumed = consumed
|
||||
|
||||
val insets = lastInsets
|
||||
if (insets != null) {
|
||||
child.dispatchApplyWindowInsets(insets)
|
||||
}
|
||||
|
||||
lastInsets?.let(child::dispatchApplyWindowInsets)
|
||||
measureContent(parent, child, consumed)
|
||||
layoutContent(child)
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -85,21 +78,19 @@ class BottomSheetContentBehavior<V : View>(context: Context, attributeSet: Attri
|
|||
parentHeightMeasureSpec: Int,
|
||||
heightUsed: Int
|
||||
): Boolean {
|
||||
val dep = dep ?: return false
|
||||
val behavior = dep.coordinatorLayoutBehavior as NeoBottomSheetBehavior
|
||||
val consumed = behavior.calculateConsumedByBar()
|
||||
if (consumed == Int.MIN_VALUE) {
|
||||
return false
|
||||
}
|
||||
val contentWidthSpec =
|
||||
View.MeasureSpec.makeMeasureSpec(parent.measuredWidth, View.MeasureSpec.EXACTLY)
|
||||
val contentHeightSpec =
|
||||
View.MeasureSpec.makeMeasureSpec(parent.measuredHeight, View.MeasureSpec.EXACTLY)
|
||||
|
||||
measureContent(parent, child, consumed)
|
||||
child.measure(contentWidthSpec, contentHeightSpec)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onLayoutChild(parent: CoordinatorLayout, child: V, layoutDirection: Int): Boolean {
|
||||
super.onLayoutChild(parent, child, layoutDirection)
|
||||
layoutContent(child)
|
||||
child.layout(0, 0, child.measuredWidth, child.measuredHeight)
|
||||
|
||||
if (!setup) {
|
||||
child.setOnApplyWindowInsetsListener { v, insets ->
|
||||
|
@ -112,9 +103,9 @@ class BottomSheetContentBehavior<V : View>(context: Context, attributeSet: Attri
|
|||
}
|
||||
|
||||
val bars = insets.systemBarInsetsCompat
|
||||
val newBottom = max(bars.bottom, consumed)
|
||||
|
||||
insets.replaceSystemBarInsetsCompat(
|
||||
bars.left, bars.top, bars.right, (bars.bottom - consumed).coerceAtLeast(0))
|
||||
insets.replaceSystemBarInsetsCompat(bars.left, bars.top, bars.right, newBottom)
|
||||
}
|
||||
|
||||
setup = true
|
||||
|
@ -123,20 +114,6 @@ class BottomSheetContentBehavior<V : View>(context: Context, attributeSet: Attri
|
|||
return true
|
||||
}
|
||||
|
||||
private fun measureContent(parent: View, child: View, consumed: Int) {
|
||||
val contentWidthSpec =
|
||||
View.MeasureSpec.makeMeasureSpec(parent.measuredWidth, View.MeasureSpec.EXACTLY)
|
||||
val contentHeightSpec =
|
||||
View.MeasureSpec.makeMeasureSpec(
|
||||
parent.measuredHeight - consumed, View.MeasureSpec.EXACTLY)
|
||||
|
||||
child.measure(contentWidthSpec, contentHeightSpec)
|
||||
}
|
||||
|
||||
private fun layoutContent(child: View) {
|
||||
child.layout(0, 0, child.measuredWidth, child.measuredHeight)
|
||||
}
|
||||
|
||||
private fun NeoBottomSheetBehavior<*>.calculateConsumedByBar(): Int {
|
||||
val offset = calculateSlideOffset()
|
||||
if (offset == Float.MIN_VALUE || peekHeight < 0) {
|
||||
|
|
|
@ -27,7 +27,11 @@ import androidx.recyclerview.widget.GridLayoutManager
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||
|
||||
/** A [RecyclerView] that automatically applies insets to itself. */
|
||||
/**
|
||||
* A [RecyclerView] that automatically applies insets to itself.
|
||||
*
|
||||
* TODO: Correctly handle edge-to-edge regarding scroll effects and saved scroll positions.
|
||||
*/
|
||||
open class AuxioRecyclerView
|
||||
@JvmOverloads
|
||||
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
|
||||
|
|
Loading…
Reference in a new issue