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

This commit is contained in:
vfsfitvnm 2022-07-25 13:12:52 +02:00
parent 457e6712d4
commit 1d259ebaa6
3 changed files with 45 additions and 37 deletions

View file

@ -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
)

View file

@ -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

View file

@ -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