Unfortunately It's not yet supported. But you can create it yourself. You need to wrap your main content with scrollable component and animate AppBar's eleveation according to scrollState of main content.
Here is example:
/**
* AppBarScaffold displays TopAppBar above specified content. Content is wrapped with
* scrollable Column. TopAppBar's elevation is animated depending on content scroll state.
*
* Back arrow is shown only if [onBackPress] is not null
*
* @param onBackPress Call back when back arrow icon is pressed
*/
@Composable
fun AppBarScaffold(
modifier: Modifier = Modifier,
title: String = "",
onBackPress: (() -> Unit)? = null,
actions: @Composable RowScope.() -> Unit = {},
content: @Composable () -> Unit
) {
val scrollState = rememberScrollState()
val contentColor = contentColorFor(MaterialTheme.colors.background)
val elevation by animateDpAsState(if (scrollState.value == 0) 0.dp else AppBarDefaults.TopAppBarElevation)
Surface(
modifier = modifier.statusBarsPadding(),
color = MaterialTheme.colors.background,
contentColor = contentColor
) {
val topBar = @Composable { AppBar(title, onBackPress, actions, elevation) }
val body = @Composable {
Column(modifier = Modifier.verticalScroll(state = scrollState)) {
content()
}
}
SubcomposeLayout { constraints ->
val layoutWidth = constraints.maxWidth
val layoutHeight = constraints.maxHeight
val looseConstraints = constraints.copy(minWidth = 0, minHeight = 0)
layout(layoutWidth, layoutHeight) {
val topBarPlaceables = subcompose(AppBarContent.AppBar, topBar).map {
it.measure(looseConstraints)
}
val topBarHeight = topBarPlaceables.maxByOrNull { it.height }?.height ?: 0
val bodyContentHeight = layoutHeight - topBarHeight
val bodyContentPlaceables = subcompose(AppBarContent.MainContent) {
body()
}.map { it.measure(looseConstraints.copy(maxHeight = bodyContentHeight)) }
bodyContentPlaceables.forEach {
it.place(0, topBarHeight)
}
topBarPlaceables.forEach {
it.place(0, 0)
}
}
}
}
}
@Composable
fun BackArrow(onclick: () -> Unit) {
IconButton(onClick = { onclick() }) {
Icon(imageVector = Icons.Default.ArrowBack, "Back Arrow")
}
}
@Composable
private fun AppBar(
title: String = "",
onBackPress: (() -> Unit)? = null,
actions: @Composable RowScope.() -> Unit = {},
elevation: Dp
) {
var navigationIcon: @Composable (() -> Unit)? = null
onBackPress?.let {
navigationIcon = { BackArrow { onBackPress.invoke() } }
}
Surface(
color = MaterialTheme.colors.background,
contentColor = MaterialTheme.colors.onBackground,
elevation = elevation,
shape = RectangleShape
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.fillMaxWidth().padding(AppBarDefaults.ContentPadding).height(AppBarHeight)
) {
navigationIcon?.let {
Row(TitleIconModifier.align(Alignment.CenterStart), verticalAlignment = Alignment.CenterVertically) {
CompositionLocalProvider(
LocalContentAlpha provides ContentAlpha.high,
content = it
)
}
}
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth(0.5f).fillMaxHeight(),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = title,
style = MaterialTheme.typography.h4,
textAlign = TextAlign.Center
)
}
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
Row(
Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically,
content = actions
)
}
}
}
}
private val AppBarHorizontalPadding = 4.dp
private val TitleIconModifier = Modifier.fillMaxHeight().width(72.dp - AppBarHorizontalPadding)
private val AppBarHeight = 56.dp
enum class AppBarContent {
AppBar,
MainContent
}