Reputation: 2545
I am developing an Android App using Jetpack Compose and Material3.
I have a screen consisting of a TopAppBar
and a LazyColumn
as content, linked together via scrollBehavior
to achieve that nice material tonal elevation change:
I now want to add a filter-layout, which should look & feel like it's part of the top app bar
My simple implementation did not do the trick: the filter has no tonal elevation:
@Composable
fun TestScreen() {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
Scaffold(
topBar = {
Column {
TopAppBar(
title = { Text("Material3 top app bar") },
scrollBehavior = scrollBehavior,
)
Text(
text = "Filter - Filter - Filter - Filter - Filter",
modifier = Modifier
.fillMaxWidth()
.height(30.dp)
)
Divider()
}
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection)
) { contentPadding ->
LazyColumn(Modifier.padding(contentPadding)) {
items(100) { index ->
Text(
text = "item $index",
modifier = Modifier.fillMaxWidth()
)
}
}
}
}
So how do i do this correctly? Sadly, unlike Material2, there is no "empty" TopAppBar i could find.
Upvotes: 0
Views: 237
Reputation: 2545
Amiir Kalantari provided a beautiful answer :)
This answer builds on his code, making it reusable and including the correct imports. All praise goes to him for figuring out the hard part!
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.FastOutLinearInEasing
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.foundation.background
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.unit.dp
// modelled after https://stackoverflow.com/a/76475561/12871582
public fun Modifier.topAppBarBackground(
scrollBehavior: TopAppBarScrollBehavior,
): Modifier = composed {
val colorTransitionFraction = scrollBehavior.state.overlappedFraction
val fraction = if (colorTransitionFraction > 0.01f) 1f else 0f
val appBarContainerColor by animateColorAsState(
targetValue = lerp(
MaterialTheme.colorScheme.surface,
MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp),
FastOutLinearInEasing.transform(fraction)
),
animationSpec = spring(stiffness = Spring.StiffnessMediumLow), label = ""
)
background(appBarContainerColor)
}
Upvotes: 0
Reputation: 126
hello you can use this code for customize your toolbar :
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TestScreen() {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
Scaffold(
topBar = {
Column {
TopAppBar(
title = { Text("Material3 top app bar") },
scrollBehavior = scrollBehavior,
)
val colorTransitionFraction = scrollBehavior.state.overlappedFraction
val fraction = if (colorTransitionFraction > 0.01f) 1f else 0f
val appBarContainerColor by animateColorAsState(
targetValue = lerp(
MaterialTheme.colorScheme.surface,
MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp),
FastOutLinearInEasing.transform(fraction)
),
animationSpec = spring(stiffness = Spring.StiffnessMediumLow), label = ""
)
Text(
text = "Filter - Filter - Filter - Filter - Filter",
modifier = Modifier
.fillMaxWidth()
.height(30.dp)
.background(appBarContainerColor)
)
}
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection)
) { contentPadding ->
LazyColumn(Modifier.padding(contentPadding)) {
items(100) { index ->
Text(
text = "item $index",
modifier = Modifier.fillMaxWidth()
)
}
}
}
}
Upvotes: 1