Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。
そのライブラリ中のBottomAppBarについて、構成や使用方法などをまとめます。
※環境:Android Studio Koala | 2024.1.1
Kotlin 1.9.0
Compose Compiler 1.5.1
androidx.compose.material3:material3 1.1.1
UIの概要
BottomAppBarはアプリ画面の下部に表示される帯状のUIです。
基本は、Scaffoldに組み込んで使用します。
※Scaffoldについては「Compose UI:Scaffold」を参照
BottomAppBarはマテリアルデザインの指標に準拠しています。
※詳細は「マテリアルデザイン:Bottom app bar」を参照してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | Scaffold( bottomBar = { BottomAppBar( containerColor = MaterialTheme.colorScheme.primaryContainer, contentColor = MaterialTheme.colorScheme.primary, ) { Text( modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, text = "Bottom app bar" , ) } } ) { innerPadding -> Column( modifier = androidx.compose.ui.Modifier .padding(innerPadding) .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy( 16 .dp), ) { for (i in 0 .. 15 ) { Text( modifier = Modifier.padding(start = 8 .dp, end = 8 .dp), text = "スクロールアイテム(${i})" ) } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | Scaffold( bottomBar = { BottomAppBar( actions = { IconButton(onClick = { /* クリック時の処理 */ }) { Icon( imageVector = Icons.Filled.Home, contentDescription = "Home" ) } IconButton(onClick = { /* クリック時の処理 */ }) { Icon( imageVector = Icons.Filled.Edit, contentDescription = "Edit" ) } IconButton(onClick = { /* クリック時の処理 */ }) { Icon( imageVector = Icons.Filled.Search, contentDescription = "Search" ) } }, floatingActionButton = { FloatingActionButton( onClick = { /* クリック時の処理 */ }, containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary ) { Icon(Icons.Default.Add, contentDescription = "Add" ) } }, containerColor = MaterialTheme.colorScheme.primaryContainer, contentColor = MaterialTheme.colorScheme.primary ) } ) { innerPadding -> Column( modifier = androidx.compose.ui.Modifier .padding(innerPadding) .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy( 16 .dp), ) { for (i in 0 .. 15 ) { Text( modifier = Modifier.padding(start = 8 .dp, end = 8 .dp), text = "スクロールアイテム(${i})" ) } } } |
関数の引数
BottomAppBarの状態(装飾、演出など)は、引数により指定できます。
1 2 3 4 5 6 7 8 9 10 | @Composable fun BottomAppBar( modifier: Modifier = Modifier, containerColor: Color = BottomAppBarDefaults.containerColor, contentColor: Color = contentColorFor(containerColor), tonalElevation: Dp = BottomAppBarDefaults.ContainerElevation, contentPadding: PaddingValues = BottomAppBarDefaults.ContentPadding, windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets, content: @Composable RowScope.() -> Unit ) { ... } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @Composable fun BottomAppBar( actions: @Composable RowScope.() -> Unit, modifier: Modifier = Modifier, floatingActionButton: @Composable (() -> Unit)? = null , containerColor: Color = BottomAppBarDefaults.containerColor, contentColor: Color = contentColorFor(containerColor), tonalElevation: Dp = BottomAppBarDefaults.ContainerElevation, contentPadding: PaddingValues = BottomAppBarDefaults.ContentPadding, windowInsets: WindowInsets = BottomAppBarDefaults.windowInsets, ) = BottomAppBar( modifier = modifier, containerColor = containerColor, contentColor = contentColor, tonalElevation = tonalElevation, windowInsets = windowInsets, contentPadding = contentPadding ) { ... } |
引数 | 概要 | |
---|---|---|
modifier | Modifier | UI全般のCompose修飾子 |
containerColor | Color | コンテナ(バー背景)の色 |
contentColor | Color | コンテンツの色 |
tonalElevation | Dp | 重ね合わせる半透明色の色合い |
contentPadding | PaddingValues | コンテンツ周りの余白 |
windowInsets | WindowInsets | インセット(はめ込み位置) |
content (タイプ1) | @Composable RowScope.() -> Unit | コンテンツのスロット |
actions (タイプ2) | @Composable RowScope.() -> Unit | アクションのスロット |
floatingActionButton (タイプ2) | @Composable (() -> Unit)? | フローティングボタンのスロット |
関数の構成
BottomAppBarはSurfaceとRowを重ね合わせた構成になっています。
content(バーに表示する文字・アイコン)はRowに入るので、左寄り横並びの配置になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @Composable fun BottomAppBar( ... content: @Composable RowScope.() -> Unit ) { Surface( color = containerColor, contentColor = contentColor, tonalElevation = tonalElevation, shape = BottomAppBarTokens.ContainerShape.toShape(), modifier = modifier ) { Row( Modifier .fillMaxWidth() .windowInsetsPadding(windowInsets) .height(BottomAppBarTokens.ContainerHeight) .padding(contentPadding), horizontalArrangement = Arrangement.Start, verticalAlignment = Alignment.CenterVertically, content = content ) } } |
タイプ2はタイプ1の派生です。
タイプ1のcontentに、actionsとfloatingActionButtonスロットを新たに設けています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @Composable fun BottomAppBar( // タイプ2 actions: @Composable RowScope.() -> Unit, ... , floatingActionButton: @Composable (() -> Unit)? = null , ... ) = BottomAppBar( // タイプ1 ... ) { // タイプ1のcontentスロット actions() if (floatingActionButton != null ) { Spacer(Modifier.weight(1f, true )) Box( Modifier .fillMaxHeight() .padding( top = FABVerticalPadding, end = FABHorizontalPadding ), contentAlignment = Alignment.TopStart ) { floatingActionButton() } } } |
actionsスロットはRowなので、左寄り横並びの配置になります。また、floatingActionButtonスロットはBoxに入り、右寄りの配置(Spacerの効果)になります。
半透明色でオーバーレイ
コンテナ色がsurfaceの時、tonalElevationに連動したcontentColorの半透明色でバーが覆われます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Scaffold( bottomBar = { BottomAppBar( containerColor = MaterialTheme.colorScheme.surface, tonalElevation = 10 .dp, contentColor = MaterialTheme.colorScheme.primary, ) { Text( modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, text = "Bottom app bar" , ) } } ) { innerPadding -> ... } |
この機能が、どのような場面で利用されるのか、不明です。利用価値はあるのでしょうか?!
影付きのバー
Viewシステムのアプリケーションバーは影が付いていました。しかし、Jetpack composeにおけるマテリアルデザインのアプリケーションバーは影が付きません。
必要であれば、Modifier修飾子を使って影を付けることが可能です。
1 2 3 4 5 | BottomAppBar( modifier = Modifier.shadow(elevation = 10 .dp), containerColor = MaterialTheme.colorScheme.primaryContainer, contentColor = MaterialTheme.colorScheme.primary, ) { ... } |
インセットの働き
インセットはナビゲーションバーとアプリケーションバーの重なりを避ける働きをします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) enableEdgeToEdge() setContent { AppTheme { Scaffold( modifier = Modifier.fillMaxSize(), bottomBar = { BottomAppBar( containerColor = MaterialTheme.colorScheme.primaryContainer, contentColor = MaterialTheme.colorScheme.primary, // windowInsets = BottomAppBarDefaults.windowInsets // デフォルト windowInsets = WindowInsets( 0 .dp, 0 .dp, 0 .dp, 0 .dp) ) { Text( modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, text = "Bottom app bar" , ) } } ) { innerPadding -> ... } } } } |
関連記事: