Fix BottomSheet behaviour on configuration change (regression of #457e6712)
This commit is contained in:
parent
457e6712d4
commit
1d259ebaa6
3 changed files with 45 additions and 37 deletions
|
@ -216,9 +216,9 @@ class MainActivity : ComponentActivity() {
|
||||||
when (val uri = uri) {
|
when (val uri = uri) {
|
||||||
null -> {
|
null -> {
|
||||||
val playerBottomSheetState = rememberBottomSheetState(
|
val playerBottomSheetState = rememberBottomSheetState(
|
||||||
lowerBound = 0.dp,
|
dismissedBound = 0.dp,
|
||||||
collapsedBound = Dimensions.collapsedPlayer,
|
collapsedBound = Dimensions.collapsedPlayer,
|
||||||
upperBound = maxHeight,
|
expandedBound = maxHeight,
|
||||||
isExpanded = expandPlayerBottomSheet
|
isExpanded = expandPlayerBottomSheet
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -52,14 +52,14 @@ fun BottomSheet(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
peekHeight: Dp = 0.dp,
|
peekHeight: Dp = 0.dp,
|
||||||
elevation: Dp = 8.dp,
|
elevation: Dp = 8.dp,
|
||||||
onSwiped: (() -> Unit)? = null,
|
onDismiss: (() -> Unit)? = null,
|
||||||
collapsedContent: @Composable BoxScope.() -> Unit,
|
collapsedContent: @Composable BoxScope.() -> Unit,
|
||||||
content: @Composable BoxScope.() -> Unit
|
content: @Composable BoxScope.() -> Unit
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.offset {
|
.offset {
|
||||||
val y = (state.upperBound - state.value + peekHeight)
|
val y = (state.expandedBound - state.value + peekHeight)
|
||||||
.roundToPx()
|
.roundToPx()
|
||||||
.coerceAtLeast(0)
|
.coerceAtLeast(0)
|
||||||
IntOffset(x = 0, y = y)
|
IntOffset(x = 0, y = y)
|
||||||
|
@ -87,25 +87,25 @@ fun BottomSheet(
|
||||||
|
|
||||||
if (velocity.absoluteValue > 300 && initialValue != state.value) {
|
if (velocity.absoluteValue > 300 && initialValue != state.value) {
|
||||||
when (initialValue) {
|
when (initialValue) {
|
||||||
state.upperBound -> state.collapse()
|
state.expandedBound -> state.collapse()
|
||||||
state.collapsedBound -> if (initialValue > state.value && onSwiped != null) {
|
state.collapsedBound -> if (initialValue > state.value && onDismiss != null) {
|
||||||
state.swipe()
|
state.dismiss()
|
||||||
onSwiped.invoke()
|
onDismiss.invoke()
|
||||||
} else {
|
} else {
|
||||||
state.expand()
|
state.expand()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val l0 = state.lowerBound
|
val l0 = state.dismissedBound
|
||||||
val l1 = (state.collapsedBound - state.lowerBound) / 2
|
val l1 = (state.collapsedBound - state.dismissedBound) / 2
|
||||||
val l2 = (state.upperBound - state.collapsedBound) / 2
|
val l2 = (state.expandedBound - state.collapsedBound) / 2
|
||||||
val l3 = state.upperBound
|
val l3 = state.expandedBound
|
||||||
|
|
||||||
when (state.value) {
|
when (state.value) {
|
||||||
in l0..l1 -> {
|
in l0..l1 -> {
|
||||||
if (onSwiped != null) {
|
if (onDismiss != null) {
|
||||||
state.swipe()
|
state.dismiss()
|
||||||
onSwiped.invoke()
|
onDismiss.invoke()
|
||||||
} else {
|
} else {
|
||||||
state.collapse()
|
state.collapse()
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ fun BottomSheet(
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.isExpanded && (onSwiped == null || !state.isDismissed)) {
|
if (!state.isExpanded && (onDismiss == null || !state.isDismissed)) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.graphicsLayer {
|
.graphicsLayer {
|
||||||
|
@ -150,13 +150,13 @@ class BottomSheetState(
|
||||||
draggableState: DraggableState,
|
draggableState: DraggableState,
|
||||||
private val coroutineScope: CoroutineScope,
|
private val coroutineScope: CoroutineScope,
|
||||||
private val animatable: Animatable<Dp, AnimationVector1D>,
|
private val animatable: Animatable<Dp, AnimationVector1D>,
|
||||||
private val onWasExpandedChanged: (Boolean) -> Unit,
|
private val onAnchorChanged: (Int) -> Unit,
|
||||||
val collapsedBound: Dp,
|
val collapsedBound: Dp,
|
||||||
) : DraggableState by draggableState {
|
) : DraggableState by draggableState {
|
||||||
val lowerBound: Dp
|
val dismissedBound: Dp
|
||||||
get() = animatable.lowerBound!!
|
get() = animatable.lowerBound!!
|
||||||
|
|
||||||
val upperBound: Dp
|
val expandedBound: Dp
|
||||||
get() = animatable.upperBound!!
|
get() = animatable.upperBound!!
|
||||||
|
|
||||||
val value by animatable.asState()
|
val value by animatable.asState()
|
||||||
|
@ -178,14 +178,14 @@ class BottomSheetState(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collapse(animationSpec: AnimationSpec<Dp>) {
|
private fun collapse(animationSpec: AnimationSpec<Dp>) {
|
||||||
onWasExpandedChanged(false)
|
onAnchorChanged(collapsedAnchor)
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
animatable.animateTo(collapsedBound, animationSpec)
|
animatable.animateTo(collapsedBound, animationSpec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun expand(animationSpec: AnimationSpec<Dp>) {
|
fun expand(animationSpec: AnimationSpec<Dp>) {
|
||||||
onWasExpandedChanged(true)
|
onAnchorChanged(expandedAnchor)
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
animatable.animateTo(animatable.upperBound!!, animationSpec)
|
animatable.animateTo(animatable.upperBound!!, animationSpec)
|
||||||
}
|
}
|
||||||
|
@ -207,8 +207,8 @@ class BottomSheetState(
|
||||||
expand(tween(300))
|
expand(tween(300))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun swipe() {
|
fun dismiss() {
|
||||||
onWasExpandedChanged(false)
|
onAnchorChanged(dismissedAnchor)
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
animatable.animateTo(animatable.lowerBound!!)
|
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
|
@Composable
|
||||||
fun rememberBottomSheetState(
|
fun rememberBottomSheetState(
|
||||||
lowerBound: Dp,
|
dismissedBound: Dp,
|
||||||
upperBound: Dp,
|
expandedBound: Dp,
|
||||||
collapsedBound: Dp = lowerBound,
|
collapsedBound: Dp = dismissedBound,
|
||||||
isExpanded: Boolean = false
|
isExpanded: Boolean = false
|
||||||
): BottomSheetState {
|
): BottomSheetState {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
var wasExpanded by rememberSaveable {
|
var previousAnchor by rememberSaveable {
|
||||||
mutableStateOf(isExpanded)
|
mutableStateOf(if (isExpanded) expandedAnchor else collapsedAnchor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return remember(lowerBound, upperBound, collapsedBound, coroutineScope) {
|
return remember(dismissedBound, expandedBound, collapsedBound, coroutineScope) {
|
||||||
val animatable =
|
val initialValue = when (previousAnchor) {
|
||||||
Animatable(if (wasExpanded) upperBound else lowerBound, Dp.VectorConverter).also {
|
expandedAnchor -> expandedBound
|
||||||
it.updateBounds(lowerBound.coerceAtMost(upperBound), upperBound)
|
collapsedAnchor -> collapsedBound
|
||||||
|
dismissedAnchor -> dismissedBound
|
||||||
|
else -> error("Unknown BottomSheet anchor")
|
||||||
|
}
|
||||||
|
|
||||||
|
val animatable = Animatable(initialValue, Dp.VectorConverter).also {
|
||||||
|
it.updateBounds(dismissedBound.coerceAtMost(expandedBound), expandedBound)
|
||||||
}
|
}
|
||||||
|
|
||||||
BottomSheetState(
|
BottomSheetState(
|
||||||
|
@ -303,9 +313,7 @@ fun rememberBottomSheetState(
|
||||||
animatable.snapTo(animatable.value - with(density) { delta.toDp() })
|
animatable.snapTo(animatable.value - with(density) { delta.toDp() })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onWasExpandedChanged = {
|
onAnchorChanged = { previousAnchor = it },
|
||||||
wasExpanded = it
|
|
||||||
},
|
|
||||||
coroutineScope = coroutineScope,
|
coroutineScope = coroutineScope,
|
||||||
animatable = animatable,
|
animatable = animatable,
|
||||||
collapsedBound = collapsedBound
|
collapsedBound = collapsedBound
|
||||||
|
|
|
@ -147,7 +147,7 @@ fun PlayerView(
|
||||||
BottomSheet(
|
BottomSheet(
|
||||||
state = layoutState,
|
state = layoutState,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onSwiped = binder.player::clearMediaItems,
|
onDismiss = binder.player::clearMediaItems,
|
||||||
collapsedContent = {
|
collapsedContent = {
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
|
@ -315,7 +315,7 @@ fun PlayerView(
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerBottomSheet(
|
PlayerBottomSheet(
|
||||||
layoutState = rememberBottomSheetState(64.dp, layoutState.upperBound),
|
layoutState = rememberBottomSheetState(64.dp, layoutState.expandedBound),
|
||||||
isShowingLyrics = isShowingLyrics,
|
isShowingLyrics = isShowingLyrics,
|
||||||
onShowLyrics = {
|
onShowLyrics = {
|
||||||
isShowingStatsForNerds = false
|
isShowingStatsForNerds = false
|
||||||
|
|
Loading…
Add table
Reference in a new issue