Question
Jetpack Compose collapsing toolbar
I can't find any documents on the matter, is there something similar to a CollapsingToolbar
in Compose?
All I found was a mention of it here, but nothing on how to set it up
Question
I can't find any documents on the matter, is there something similar to a CollapsingToolbar
in Compose?
All I found was a mention of it here, but nothing on how to set it up
Solution
Jetpack Compose implementation of Material Design 3 includes 4 types of Top App Bars (https://m3.material.io/components/top-app-bar/implementation):
CenterAlignedTopAppBar
SmallTopAppBar
MediumTopAppBar
LargeTopAppBar
https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary
They all have a scrollBehavior
parameter, which can be used for collapsing the toolbar. There are 3 basic types of scroll behavior in the library:
TopAppBarDefaults.pinnedScrollBehavior
TopAppBarDefaults.enterAlwaysScrollBehavior
TopAppBarDefaults.exitUntilCollapsedScrollBehavior
https://developer.android.com/reference/kotlin/androidx/compose/material3/TopAppBarDefaults
Note: This API is annotated as experimental at the moment.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Test() {
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState())
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
MediumTopAppBar(
title = { Text(text = "Scroll Behavior Test") },
navigationIcon = {
IconButton(onClick = { /*TODO*/ }) {
Icon(imageVector = Icons.Default.Menu, contentDescription = "")
}
},
scrollBehavior = scrollBehavior
)
}
) {
LazyColumn(modifier = Modifier.fillMaxWidth()) {
items((1..50).toList()) { item ->
Text(modifier = Modifier.padding(8.dp), text = "Item $item")
}
}
}
}
Solution
I found a solution created by Samir Basnet (from Kotlin Slack Channel) which was useful for me, I hope it helps someone else...
@Composable
fun CollapsingEffectScreen() {
val items = (1..100).map { "Item $it" }
val lazyListState = rememberLazyListState()
var scrolledY = 0f
var previousOffset = 0
LazyColumn(
Modifier.fillMaxSize(),
lazyListState,
) {
item {
Image(
painter = painterResource(id = R.drawable.recife),
contentDescription = null,
contentScale = ContentScale.FillWidth,
modifier = Modifier
.graphicsLayer {
scrolledY += lazyListState.firstVisibleItemScrollOffset - previousOffset
translationY = scrolledY * 0.5f
previousOffset = lazyListState.firstVisibleItemScrollOffset
}
.height(240.dp)
.fillMaxWidth()
)
}
items(items) {
Text(
text = it,
Modifier
.background(Color.White)
.fillMaxWidth()
.padding(8.dp)
)
}
}
}
Here is the result: