I'm writing an android-app using jetpack compose.
This app has a bottom bar which i would like to hide sometimes using an animation. However, this proved challenging: as soon as i was dealing with a scrollable screen, there was some "jumping" of my ui - see end of post.
My minimal example looks like:
@Preview
@Composable
fun JumpingBottomBarScreen() {
var bottomBarVisible by remember { mutableStateOf(false) }
Scaffold(
content = { padding ->
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxWidth()
.background(Color.LightGray)
.padding(padding)
) {
(1..20).forEach { Text(text = "Test #$it of 50") }
Button(
onClick = { bottomBarVisible = !bottomBarVisible },
content = { Text(if (bottomBarVisible) "Hide Bottom Bar" else "Show Bottom Bar") }
)
(21..50).forEach { Text(text = "Test #$it of 50") }
}
},
bottomBar = {
AnimatedVisibility(
visible = bottomBarVisible,
enter = slideInVertically(initialOffsetY = { it }),
exit = slideOutVertically(targetOffsetY = { it })
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.background(Color.Red)
)
}
}
)
}
Avoiding AnimatedVisibility
in favor of just offsetting works better, however, i only managed for fixed height bottom-bars, which makes this much less fail-safe.
bottomBar = {
val bottomBarOffset by animateDpAsState(targetValue = if (bottomBarVisible) 0.dp else 50.dp)
Box(
modifier = Modifier
.offset(y = bottomBarOffset)
.fillMaxWidth()
.height(50.dp)
.background(Color.Red)
)
}
How do i do this cleanly? I'm fine with my screen having more padding at the bottom than expected.
Bad on the left/top, good (but fixed height) on the right/bottom
You need to animate your Column padding as well: