playback: make bottom sheet behavior more in-spec

Don't gradually fade out until the very end, reduce the corner radii
at the very end, fix elevation, delift elevation at the very end.

More tweaks are probably needed here to make it look good.
This commit is contained in:
Alexander Capehart 2024-04-19 11:04:24 -06:00
parent fc90d460dc
commit 9990e00a4a
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
7 changed files with 57 additions and 31 deletions

View file

@ -26,13 +26,13 @@ import androidx.activity.OnBackPressedCallback
import androidx.core.view.ViewCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import com.google.android.material.R as MR
import com.google.android.material.bottomsheet.BackportBottomSheetBehavior
import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.shape.ShapeAppearanceModel
import com.google.android.material.transition.MaterialFadeThrough
import com.leinardi.android.speeddial.SpeedDialOverlayLayout
import dagger.hilt.android.AndroidEntryPoint
@ -62,7 +62,6 @@ import org.oxycblt.auxio.util.getDimen
import org.oxycblt.auxio.util.lazyReflectedField
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.systemBarInsetsCompat
import org.oxycblt.auxio.util.unlikelyToBeNull
/**
@ -84,6 +83,7 @@ class MainFragment :
private var selectionNavigationListener: DialogAwareNavigationListener? = null
private var lastInsets: WindowInsets? = null
private var elevationNormal = 0f
private var normalCornerSize = 0f
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -146,16 +146,22 @@ class MainFragment :
// Emulate the elevated bottom sheet style.
background =
MaterialShapeDrawable.createWithElevationOverlay(context).apply {
val cornerSize =
context.resources.getDimension(R.dimen.size_corners_mid_large)
shapeAppearanceModel =
ShapeAppearanceModel.builder()
.setTopLeftCornerSize(cornerSize)
.setTopRightCornerSize(cornerSize)
.build()
fillColor = context.getAttrColorCompat(MR.attr.colorSurfaceContainerHigh)
}
// Apply bar insets for the queue's RecyclerView to use.
setOnApplyWindowInsetsListener { v, insets ->
v.updatePadding(top = insets.systemBarInsetsCompat.top)
insets
}
}
}
normalCornerSize = playbackSheetBehavior.sheetBackgroundDrawable.topLeftCornerResolvedSize
binding.playbackSheet.elevation = 0f
binding.mainScrim.setOnClickListener { homeModel.setSpeedDialOpen(false) }
binding.sheetScrim.setOnClickListener { homeModel.setSpeedDialOpen(false) }
@ -241,6 +247,14 @@ class MainFragment :
val halfOutRatio = min(playbackRatio * 2, 1f)
val halfInPlaybackRatio = max(playbackRatio - 0.5f, 0f) * 2
val lastStretchRatio = max(playbackRatio - 0.9f, 0f) / 0.1f
binding.mainSheetScrim.alpha = lastStretchRatio
playbackSheetBehavior.sheetBackgroundDrawable.setCornerSize(
normalCornerSize * (1 - lastStretchRatio))
binding.exploreNavHost.isInvisible = playbackRatio == 1f
binding.playbackSheet.translationZ = (1 - lastStretchRatio) * elevationNormal
if (queueSheetBehavior != null) {
// Queue sheet available, the normal transition applies, but it now much be combined
// with another transition where the playback panel disappears and the playback bar
@ -263,31 +277,16 @@ class MainFragment :
// No queue sheet, fade normally based on the playback sheet
binding.playbackBarFragment.alpha = 1 - halfOutRatio
binding.playbackPanelFragment.alpha = halfInPlaybackRatio
(binding.queueSheet.background as MaterialShapeDrawable).shapeAppearanceModel =
ShapeAppearanceModel.builder()
.setTopLeftCornerSize(normalCornerSize)
.setTopRightCornerSize(normalCornerSize * (1 - lastStretchRatio))
.build()
}
// Fade out the content as the playback panel expands.
// TODO: Replace with shadow?
binding.exploreNavHost.apply {
alpha = outPlaybackRatio
// Prevent interactions when the content fully fades out.
isInvisible = alpha == 0f
}
// Reduce playback sheet elevation as it expands. This involves both updating the
// shadow elevation for older versions, and fading out the background drawable
// containing the elevation overlay.
binding.playbackSheet.elevation = elevationNormal * outPlaybackRatio
playbackSheetBehavior.sheetBackgroundDrawable.alpha = (outPlaybackRatio * 255).toInt()
// Fade out the playback bar as the panel expands.
binding.playbackBarFragment.apply {
// Prevent interactions when the playback bar fully fades out.
isInvisible = alpha == 0f
// As the playback bar expands, we also want to subtly translate the bar to
// align with the top inset. This results in both a smooth transition from the bar
// to the playback panel's toolbar, but also a correctly positioned playback bar
// for when the queue sheet expands.
lastInsets?.let { translationY = it.systemBarInsetsCompat.top * halfOutRatio }
}
// Prevent interactions when the playback panel fully fades out.

View file

@ -23,12 +23,15 @@ import android.graphics.drawable.LayerDrawable
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.WindowInsets
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.R as MR
import com.google.android.material.shape.MaterialShapeDrawable
import org.oxycblt.auxio.R
import org.oxycblt.auxio.ui.BaseBottomSheetBehavior
import org.oxycblt.auxio.util.getAttrColorCompat
import org.oxycblt.auxio.util.replaceSystemBarInsetsCompat
import org.oxycblt.auxio.util.systemBarInsetsCompat
/**
* The [BaseBottomSheetBehavior] for the playback bottom sheet. This bottom sheet
@ -64,4 +67,14 @@ class PlaybackBottomSheetBehavior<V : View>(context: Context, attributeSet: Attr
fillColor = sheetBackgroundDrawable.fillColor
},
sheetBackgroundDrawable))
override fun applyWindowInsets(child: View, insets: WindowInsets): WindowInsets {
super.applyWindowInsets(child, insets)
// Offset our expanded panel by the size of the playback bar, as that is shown when
// we slide up the panel.
val bars = insets.systemBarInsetsCompat
expandedOffset = bars.top
return insets.replaceSystemBarInsetsCompat(
bars.left, bars.top, bars.right, expandedOffset + bars.bottom)
}
}

View file

@ -87,7 +87,7 @@ class PlaybackPanelFragment :
// --- UI SETUP ---
binding.root.setOnApplyWindowInsetsListener { view, insets ->
val bars = insets.systemBarInsetsCompat
view.updatePadding(top = bars.top, bottom = bars.bottom)
view.updatePadding(bottom = bars.bottom)
insets
}

View file

@ -73,7 +73,7 @@ class QueueBottomSheetBehavior<V : View>(context: Context, attributeSet: Attribu
// Offset our expanded panel by the size of the playback bar, as that is shown when
// we slide up the panel.
val bars = insets.systemBarInsetsCompat
expandedOffset = bars.top + barHeight + barSpacing
expandedOffset = barHeight + barSpacing
return insets.replaceSystemBarInsetsCompat(
bars.left, bars.top, bars.right, expandedOffset + bars.bottom)
}

View file

@ -19,6 +19,13 @@
<View android:id="@+id/main_scrim" android:layout_height="match_parent" android:layout_width="match_parent"/>
<View
android:id="@+id/main_sheet_scrim"
android:background="?attr/colorSurfaceContainerLow"
android:layout_width="match_parent"
android:alpha="0"
android:layout_height="match_parent" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/playback_sheet"
android:layout_width="match_parent"

View file

@ -23,6 +23,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:id="@+id/main_sheet_scrim"
android:background="?attr/colorSurfaceContainerLow"
android:layout_width="match_parent"
android:alpha="0"
android:layout_height="match_parent" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/playback_sheet"
android:layout_width="match_parent"
@ -47,7 +54,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
style="@style/Widget.Auxio.DisableDropShadows"
android:elevation="1dp"
app:layout_behavior="org.oxycblt.auxio.playback.queue.QueueBottomSheetBehavior">
<androidx.constraintlayout.widget.ConstraintLayout

View file

@ -42,7 +42,7 @@
<dimen name="slider_thumb_height">24dp</dimen>
<!-- Misc -->
<dimen name="elevation_normal">6dp</dimen>
<dimen name="elevation_normal">1dp</dimen>
<dimen name="fast_scroll_popup_min_width">78dp</dimen>
<dimen name="fast_scroll_popup_min_height">64dp</dimen>