소스 검색

Fix BottomSheet behaviour on configuration change (regression of #457e6712)

vfsfitvnm 2 년 전
부모
커밋
1d259ebaa6

+ 2 - 2
app/src/main/kotlin/it/vfsfitvnm/vimusic/MainActivity.kt

@@ -216,9 +216,9 @@ class MainActivity : ComponentActivity() {
                     when (val uri = uri) {
                         null -> {
                             val playerBottomSheetState = rememberBottomSheetState(
-                                lowerBound = 0.dp,
+                                dismissedBound = 0.dp,
                                 collapsedBound = Dimensions.collapsedPlayer,
-                                upperBound = maxHeight,
+                                expandedBound = maxHeight,
                                 isExpanded = expandPlayerBottomSheet
                             )
 

+ 41 - 33
app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/BottomSheet.kt

@@ -52,14 +52,14 @@ fun BottomSheet(
     modifier: Modifier = Modifier,
     peekHeight: Dp = 0.dp,
     elevation: Dp = 8.dp,
-    onSwiped: (() -> Unit)? = null,
+    onDismiss: (() -> Unit)? = null,
     collapsedContent: @Composable BoxScope.() -> Unit,
     content: @Composable BoxScope.() -> Unit
 ) {
     Box(
         modifier = modifier
             .offset {
-                val y = (state.upperBound - state.value + peekHeight)
+                val y = (state.expandedBound - state.value + peekHeight)
                     .roundToPx()
                     .coerceAtLeast(0)
                 IntOffset(x = 0, y = y)
@@ -87,25 +87,25 @@ fun BottomSheet(
 
                         if (velocity.absoluteValue > 300 && initialValue != state.value) {
                             when (initialValue) {
-                                state.upperBound -> state.collapse()
-                                state.collapsedBound -> if (initialValue > state.value && onSwiped != null) {
-                                    state.swipe()
-                                    onSwiped.invoke()
+                                state.expandedBound -> state.collapse()
+                                state.collapsedBound -> if (initialValue > state.value && onDismiss != null) {
+                                    state.dismiss()
+                                    onDismiss.invoke()
                                 } else {
                                     state.expand()
                                 }
                             }
                         } else {
-                            val l0 = state.lowerBound
-                            val l1 = (state.collapsedBound - state.lowerBound) / 2
-                            val l2 = (state.upperBound - state.collapsedBound) / 2
-                            val l3 = state.upperBound
+                            val l0 = state.dismissedBound
+                            val l1 = (state.collapsedBound - state.dismissedBound) / 2
+                            val l2 = (state.expandedBound - state.collapsedBound) / 2
+                            val l3 = state.expandedBound
 
                             when (state.value) {
                                 in l0..l1 -> {
-                                    if (onSwiped != null) {
-                                        state.swipe()
-                                        onSwiped.invoke()
+                                    if (onDismiss != null) {
+                                        state.dismiss()
+                                        onDismiss.invoke()
                                     } else {
                                         state.collapse()
                                     }
@@ -126,7 +126,7 @@ fun BottomSheet(
             content()
         }
 
-        if (!state.isExpanded && (onSwiped == null || !state.isDismissed)) {
+        if (!state.isExpanded && (onDismiss == null || !state.isDismissed)) {
             Box(
                 modifier = Modifier
                     .graphicsLayer {
@@ -150,13 +150,13 @@ class BottomSheetState(
     draggableState: DraggableState,
     private val coroutineScope: CoroutineScope,
     private val animatable: Animatable<Dp, AnimationVector1D>,
-    private val onWasExpandedChanged: (Boolean) -> Unit,
+    private val onAnchorChanged: (Int) -> Unit,
     val collapsedBound: Dp,
 ) : DraggableState by draggableState {
-    val lowerBound: Dp
+    val dismissedBound: Dp
         get() = animatable.lowerBound!!
 
-    val upperBound: Dp
+    val expandedBound: Dp
         get() = animatable.upperBound!!
 
     val value by animatable.asState()
@@ -178,14 +178,14 @@ class BottomSheetState(
     }
 
     private fun collapse(animationSpec: AnimationSpec<Dp>) {
-        onWasExpandedChanged(false)
+        onAnchorChanged(collapsedAnchor)
         coroutineScope.launch {
             animatable.animateTo(collapsedBound, animationSpec)
         }
     }
 
     fun expand(animationSpec: AnimationSpec<Dp>) {
-        onWasExpandedChanged(true)
+        onAnchorChanged(expandedAnchor)
         coroutineScope.launch {
             animatable.animateTo(animatable.upperBound!!, animationSpec)
         }
@@ -207,8 +207,8 @@ class BottomSheetState(
         expand(tween(300))
     }
 
-    fun swipe() {
-        onWasExpandedChanged(false)
+    fun dismiss() {
+        onAnchorChanged(dismissedAnchor)
         coroutineScope.launch {
             animatable.animateTo(animatable.lowerBound!!)
         }
@@ -277,24 +277,34 @@ class BottomSheetState(
     }
 }
 
+private const val expandedAnchor = 2
+private const val collapsedAnchor = 1
+private const val dismissedAnchor = 0
+
 @Composable
 fun rememberBottomSheetState(
-    lowerBound: Dp,
-    upperBound: Dp,
-    collapsedBound: Dp = lowerBound,
+    dismissedBound: Dp,
+    expandedBound: Dp,
+    collapsedBound: Dp = dismissedBound,
     isExpanded: Boolean = false
 ): BottomSheetState {
     val density = LocalDensity.current
     val coroutineScope = rememberCoroutineScope()
 
-    var wasExpanded by rememberSaveable {
-        mutableStateOf(isExpanded)
+    var previousAnchor by rememberSaveable {
+        mutableStateOf(if (isExpanded) expandedAnchor else collapsedAnchor)
     }
 
-    return remember(lowerBound, upperBound, collapsedBound, coroutineScope) {
-        val animatable =
-            Animatable(if (wasExpanded) upperBound else lowerBound, Dp.VectorConverter).also {
-                it.updateBounds(lowerBound.coerceAtMost(upperBound), upperBound)
+    return remember(dismissedBound, expandedBound, collapsedBound, coroutineScope) {
+        val initialValue = when (previousAnchor) {
+            expandedAnchor -> expandedBound
+            collapsedAnchor -> collapsedBound
+            dismissedAnchor -> dismissedBound
+            else -> error("Unknown BottomSheet anchor")
+        }
+
+        val animatable = Animatable(initialValue, Dp.VectorConverter).also {
+                it.updateBounds(dismissedBound.coerceAtMost(expandedBound), expandedBound)
             }
 
         BottomSheetState(
@@ -303,9 +313,7 @@ fun rememberBottomSheetState(
                     animatable.snapTo(animatable.value - with(density) { delta.toDp() })
                 }
             },
-            onWasExpandedChanged = {
-                wasExpanded = it
-            },
+            onAnchorChanged = { previousAnchor = it },
             coroutineScope = coroutineScope,
             animatable = animatable,
             collapsedBound = collapsedBound

+ 2 - 2
app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/views/PlayerView.kt

@@ -147,7 +147,7 @@ fun PlayerView(
     BottomSheet(
         state = layoutState,
         modifier = modifier,
-        onSwiped = binder.player::clearMediaItems,
+        onDismiss = binder.player::clearMediaItems,
         collapsedContent = {
             Row(
                 horizontalArrangement = Arrangement.spacedBy(12.dp),
@@ -315,7 +315,7 @@ fun PlayerView(
         }
 
         PlayerBottomSheet(
-            layoutState = rememberBottomSheetState(64.dp, layoutState.upperBound),
+            layoutState = rememberBottomSheetState(64.dp, layoutState.expandedBound),
             isShowingLyrics = isShowingLyrics,
             onShowLyrics = {
                 isShowingStatsForNerds = false