playback: use layer background in playback panel
Use a layered background in the playback panel, with a colorSurface layer behind the elevated MaterialShapeDrawable. This is for safety, as there might be cases where a fully transparent MaterialShapeDrawable results in unexpected behavior.
This commit is contained in:
parent
2ae22500d3
commit
56ded96b10
2 changed files with 41 additions and 13 deletions
|
@ -5,6 +5,7 @@ import android.content.res.ColorStateList
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Insets
|
import android.graphics.Insets
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
import android.graphics.drawable.LayerDrawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
@ -25,6 +26,7 @@ import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
import org.oxycblt.auxio.util.resolveAttr
|
import org.oxycblt.auxio.util.resolveAttr
|
||||||
|
import org.oxycblt.auxio.util.resolveDrawable
|
||||||
import org.oxycblt.auxio.util.systemBarsCompat
|
import org.oxycblt.auxio.util.systemBarsCompat
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
@ -34,12 +36,14 @@ import kotlin.math.min
|
||||||
* This layout handles pretty much every aspect of the playback UI flow, notably the playback
|
* This layout handles pretty much every aspect of the playback UI flow, notably the playback
|
||||||
* bar and it's ability to slide up into the playback view. It's a blend of Hai Zhang's
|
* bar and it's ability to slide up into the playback view. It's a blend of Hai Zhang's
|
||||||
* PersistentBarLayout and Umano's SlidingUpPanelLayout, albeit heavily minified to remove
|
* PersistentBarLayout and Umano's SlidingUpPanelLayout, albeit heavily minified to remove
|
||||||
* extraneous use cases and updated to support the latest SDK level.
|
* extraneous use cases and updated to support the latest SDK level and androidx tools.
|
||||||
*
|
*
|
||||||
* **Note:** If you want to adapt this layout into your own app. Good luck. This layout has been
|
* **Note:** If you want to adapt this layout into your own app. Good luck. This layout has been
|
||||||
* heavily minified to Auxio's use case in particular and is really hard to understand since it
|
* reduced to Auxio's use case in particular and is really hard to understand since it has a ton
|
||||||
* has a ton of state and view magic. I tried my best to document it, but it's probably not the
|
* of state and view magic. I tried my best to document it, but it's probably not the most friendly
|
||||||
* most friendly or extendable. You have been warned.
|
* or extendable. You have been warned.
|
||||||
|
*
|
||||||
|
* @author OxygenCobalt (With help from Umano and Hai Zhang)
|
||||||
*/
|
*/
|
||||||
class PlaybackLayout @JvmOverloads constructor(
|
class PlaybackLayout @JvmOverloads constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
@ -61,6 +65,8 @@ class PlaybackLayout @JvmOverloads constructor(
|
||||||
private val playbackContainerView: FrameLayout
|
private val playbackContainerView: FrameLayout
|
||||||
private val playbackBarView: PlaybackBarView
|
private val playbackBarView: PlaybackBarView
|
||||||
private val playbackPanelView: FrameLayout
|
private val playbackPanelView: FrameLayout
|
||||||
|
|
||||||
|
private val playbackContainerBg: MaterialShapeDrawable
|
||||||
private val playbackFragment = PlaybackFragment()
|
private val playbackFragment = PlaybackFragment()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,10 +100,16 @@ class PlaybackLayout @JvmOverloads constructor(
|
||||||
*/
|
*/
|
||||||
private var panelOffset = 0f
|
private var panelOffset = 0f
|
||||||
|
|
||||||
|
// Miscellaneous view things
|
||||||
private var initMotionX = 0f
|
private var initMotionX = 0f
|
||||||
private var initMotionY = 0f
|
private var initMotionY = 0f
|
||||||
private val tRect = Rect()
|
private val tRect = Rect()
|
||||||
|
|
||||||
|
/** See [isDragging] */
|
||||||
|
private val dragStateField = ViewDragHelper::class.java.getDeclaredField("mDragState").apply {
|
||||||
|
isAccessible = true
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setWillNotDraw(false)
|
setWillNotDraw(false)
|
||||||
|
|
||||||
|
@ -110,10 +122,18 @@ class PlaybackLayout @JvmOverloads constructor(
|
||||||
isFocusable = false
|
isFocusable = false
|
||||||
isFocusableInTouchMode = false
|
isFocusableInTouchMode = false
|
||||||
|
|
||||||
background = MaterialShapeDrawable.createWithElevationOverlay(context).apply {
|
playbackContainerBg = MaterialShapeDrawable.createWithElevationOverlay(context).apply {
|
||||||
fillColor = ColorStateList.valueOf(R.attr.colorSurface.resolveAttr(context))
|
fillColor = ColorStateList.valueOf(R.attr.colorSurface.resolveAttr(context))
|
||||||
elevation = resources.getDimensionPixelSize(R.dimen.elevation_normal).toFloat()
|
elevation = resources.getDimensionPixelSize(R.dimen.elevation_normal).toFloat()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The way we fade out the elevation overlay is not by actually reducing the elevation
|
||||||
|
// but by fading out the background drawable itself. To be safe, we apply this
|
||||||
|
// background drawable to a layer list with another colorSurface shape drawable, just
|
||||||
|
// in case weird things happen if background drawable is completely transparent.
|
||||||
|
background = (R.drawable.ui_panel_bg.resolveDrawable(context) as LayerDrawable).apply {
|
||||||
|
setDrawableByLayerId(R.id.panel_overlay, playbackContainerBg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playbackBarView = PlaybackBarView(context).apply {
|
playbackBarView = PlaybackBarView(context).apply {
|
||||||
|
@ -205,7 +225,6 @@ class PlaybackLayout @JvmOverloads constructor(
|
||||||
logD(panelState)
|
logD(panelState)
|
||||||
if (panelState == PanelState.EXPANDED) {
|
if (panelState == PanelState.EXPANDED) {
|
||||||
applyState(PanelState.COLLAPSED)
|
applyState(PanelState.COLLAPSED)
|
||||||
logD("I AM EXPANDED WILL COLLAPSE")
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,10 +531,7 @@ class PlaybackLayout @JvmOverloads constructor(
|
||||||
// We can't grab the drag state outside of a callback, but that's stupid and I don't
|
// We can't grab the drag state outside of a callback, but that's stupid and I don't
|
||||||
// want to vendor ViewDragHelper so I just do reflection instead.
|
// want to vendor ViewDragHelper so I just do reflection instead.
|
||||||
val state = try {
|
val state = try {
|
||||||
this::class.java.getDeclaredField("mDragState").run {
|
dragStateField.get(this)
|
||||||
isAccessible = true
|
|
||||||
get(dragHelper) as Int
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
ViewDragHelper.STATE_IDLE
|
ViewDragHelper.STATE_IDLE
|
||||||
}
|
}
|
||||||
|
@ -549,9 +565,9 @@ class PlaybackLayout @JvmOverloads constructor(
|
||||||
// Optimize out drawing for this view completely
|
// Optimize out drawing for this view completely
|
||||||
contentView.isInvisible = outRatio == 0f
|
contentView.isInvisible = outRatio == 0f
|
||||||
|
|
||||||
// Slowly reduce the elevation as we slide up, eventually resulting in a neutral color
|
// Slowly reduce the elevation of the container as we slide up, eventually resulting in a
|
||||||
// instead of an elevated one when fully expanded.
|
// neutral color instead of an elevated one when fully expanded.
|
||||||
(playbackContainerView.background as MaterialShapeDrawable).alpha = (outRatio * 255).toInt()
|
playbackContainerBg.alpha = (outRatio * 255).toInt()
|
||||||
|
|
||||||
// Fade out our bar view as we slide up
|
// Fade out our bar view as we slide up
|
||||||
playbackBarView.apply {
|
playbackBarView.apply {
|
||||||
|
|
12
app/src/main/res/drawable/ui_panel_bg.xml
Normal file
12
app/src/main/res/drawable/ui_panel_bg.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@android:id/background">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="?attr/colorSurface" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<item android:id="@+id/panel_overlay">
|
||||||
|
<shape android:shape="rectangle" />
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
Loading…
Reference in a new issue