先日投稿した、Material 3で大きく変わったTopAppBarをJetpack Composeで実装してみる の補足記事になります。
前回の記事で紹介した androidx.compose.material3
の TopAppBar ですが、そのまま実装すると StatusBar の下まで表示させる Edge to edge の対応ができません。
androidx.compose.material
の方は Accompanist の Inset がその辺りの実装をライブラリとして提供してくれていますが、androidx.compose.material3
の方は存在しない ( issue は立っている) ので実装が必要になります。
Accompanist で提供されそうな予感もしつつ、対応するための実装を書いていこうと思います。
(Accompanist の Inset 周りのコードの説明は省略します。)
TopAppBar に padding を設定しても背景色は適用されない
以下のコードのように TopAppBar に StatusBar の高さ分の padding を設定すると StatusBar の部分に空白ができるて背景色が反映されない状態になります。
Jetpack Compose の modifier の挙動ではあるものの、StatusBar の下まで TopAppBar の背景色を表示させたいのでこれだと対応が不十分です。
@Composable
fun ExampleScreen() {
val statusBarPadding = rememberInsetsPaddingValues(
LocalWindowInsets.current.statusBars,
applyBottom = false,
)
val scrollBehavior = remember { TopAppBarDefaults.pinnedScrollBehavior() }
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
SmallTopAppBar(
title = {
Text(text = "Title")
},
navigationIcon = {
BackIconButton {
}
},
scrollBehavior = scrollBehavior,
modifier = Modifier.padding(statusBarPadding),
)
}
) {
// contents
}
}
実装
以下のようなコードで TopAppBar に padding を適用しても背景色が適用されるようにします
- TopAppBar の背景色は透明にする
-
Surface
側で本来 TopAppBar で表示されるはずの背景色をセットする - 外から padding を設定できるようにして TopAppBar 側にセットする
(SmallTopAppBar
のコードになりますが、Medium や Large も同じ要領で実装できます。)
@Composable
fun SmallTopAppBar(
title: @Composable () -> Unit,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
colors: TopAppBarColors = TopAppBarDefaults.smallTopAppBarColors(),
scrollBehavior: TopAppBarScrollBehavior? = null,
) {
val backgroundColor = colors.containerColor(
scrollFraction = scrollBehavior?.scrollFraction ?: 0.0f
).value
Surface(
color = backgroundColor,
modifier = modifier,
) {
androidx.compose.material3.SmallTopAppBar(
title = title,
navigationIcon = navigationIcon,
actions = actions,
scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.smallTopAppBarColors(
containerColor = Color.Transparent,
scrolledContainerColor = Color.Transparent
),
modifier = Modifier.padding(contentPadding),
)
}
}
ここで実装した TopAppBar を使うことで StatusBar の下まで TopAppBar を正しく表示させることができます。
@Composable
fun ExampleScreen() {
val statusBarPadding = rememberInsetsPaddingValues(
LocalWindowInsets.current.statusBars,
applyBottom = false,
)
val scrollBehavior = remember { TopAppBarDefaults.pinnedScrollBehavior() }
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
SmallTopAppBar(
title = {
Text(text = "Title")
},
navigationIcon = {
BackIconButton {
}
},
scrollBehavior = scrollBehavior,
contentPadding = statusBarPadding,
)
}
) {
// contents
}
}