Compose UI:TopAppBar

投稿日:  更新日:

Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。

そのライブラリ中のTopAppBarについて、構成や使用方法などをまとめます。

※環境:Android Studio Koala | 2024.1.1
    Kotlin 1.9.0
    Compose Compiler 1.5.1
    androidx.compose.material3:material3 1.1.1

スポンサーリンク

UIの概要

TopAppBarはアプリ画面の上部に表示される帯状のUIです。

基本は、Scaffoldに組み込んで使用します。
※Scaffoldについては「Compose UI:Scaffold」を参照

    Scaffold(
        topBar = {
		    @OptIn(ExperimentalMaterial3Api::class)
            TopAppBar(
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.primaryContainer,
                    titleContentColor = MaterialTheme.colorScheme.primary,
                ),
                title = { Text("Top app bar") },
                navigationIcon = {
                    IconButton(onClick = { /* クリック時の処理 */ }) {
                        Icon(
                            imageVector = Icons.Filled.ArrowBack,
                            contentDescription = "Back"
                        )
                    }
                },
                actions = {
                    IconButton(onClick = { /* クリック時の処理 */ }) {
                        Icon(
                            imageVector = Icons.Filled.Menu,
                            contentDescription = "Menu"
                        )
                    }
                }
            )
        }
    ) { innerPadding ->
        Column(
            modifier = 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})"
                )
            }
        }
    }

TopAppBarの概要

TopAppBarはマテリアルデザインの指標に準拠しています。

帯の左端に「ナビケーション」、右端に「アクション」、真ん中に「タイトル」を配置するレイアウトが標準です。
※詳細は「マテリアルデザイン:Top app bars」を参照してください。

スポンサーリンク

関数の引数

TopAppBarの状態(装飾、演出など)は、引数により指定できます。

@ExperimentalMaterial3Api
@Composable
fun TopAppBar(
    title: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    navigationIcon: @Composable () -> Unit = {},
    actions: @Composable RowScope.() -> Unit = {},
    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
    scrollBehavior: TopAppBarScrollBehavior? = null
) { ... }
引数概要
title@Composable () -> Unitタイトルのスロット
modifierModifierUI全般のCompose修飾子
navigationIcon@Composable () -> Unitナビゲーションのスロット
actions@Composable RowScope.() -> Unitアクションのスロット
windowInsetsWindowInsets インセット(はめ込み位置)
colorsTopAppBarColors バーの配色
・コンテナ(containerColor)
・タイトル(titleContentColor)
・ナビゲーションアイコン
 (navigationIconContentColor)
・アクションアイコン
 (actionIconContentColor)
・スクロール時のコンテナ
 (scrolledContainerColor)
scrollBehaviorTopAppBarScrollBehavior?NestedScrollから状態の通知
スポンサーリンク

派生タイプ

TopAppBar関数をベースにした派生タイプが定義されています。

【注意】

TopAppBarは「アノテーション:@ExperimentalMaterial3Api」付きです。

@ExperimentalMaterial3Apiは「実験的なAPI」を意味します。

ですので、今後のリリースで変更や削除の可能性があります。その点を理解した上で使用する必要があります。

使用に際して、上記の点についての許諾(アノテーション:@OptIn)が求められます。

サンプル:派生タイプ
    Scaffold(
        topBar = {
		    @OptIn(ExperimentalMaterial3Api::class)
            TopAppBar(
            // CenterAlignedTopAppBar(
            // MediumTopAppBar(
            // LargeTopAppBar(
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.primaryContainer,
                    titleContentColor = MaterialTheme.colorScheme.primary,
                ),
                title = { Text("Top app bar") },
                navigationIcon = {
                    IconButton(onClick = { /* クリック時の処理 */ }) {
                        Icon(
                            imageVector = Icons.Filled.ArrowBack,
                            contentDescription = "Back"
                        )
                    }
                },
                actions = {
                    IconButton(onClick = { /* クリック時の処理 */ }) {
                        Icon(
                            imageVector = Icons.Filled.Menu,
                            contentDescription = "Menu"
                        )
                    }
                }
            )
        }
    ) { innerPadding ->
        Column(
            modifier = 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})"
                )
            }
        }
    }

(Small)TopAppBar(ベース)

タイトルが帯の右側に表示されます。高さはバー1つ分です。

(Small)TopAppBarサンプル

TopAppBarは派生タイプのベースになる関数です。

CenterAlignedTopAppBar

タイトルが帯の中央に表示されます。高さはバー1つ分です。

CenterAlignedTopAppBarサンプル

MediumTopAppBar

ナビゲーション・アクションとタイトルが分かれて表示されます。高さはバー2つ分です。

MediumTopAppBarサンプル

タイトル欄が広く使える利点があります。しかし、タイトルのスロットに入るUIとしてText(Conpose UI)を想定おり、拡張性は低いです。

LargeTopAppBar

ナビゲーション・アクションとタイトルが分かれて表示されます。高さはバー2つ分です。タイトルが他の派生タイプよりも大きく表示されます。

LargeTopAppBarサンプル

タイトル欄が広く使える利点があります。しかし、タイトルのスロットに入るUIとしてText(Conpose UI)を想定おり、拡張性は低いです。

スポンサーリンク

関数の構成

TopAppBar関数(派生タイプを含む)は内部でSingle/TwoRowTopAppBar関数を呼び出しています。

TopAppBarの構成

 SingleRowTopAppBar 

1つのバーで構成されます。高さはバー1つ分です。

 TwoRowTopAppBar 

上下に並ぶ2つのバーで構成されます。高さはバー2つ分です。上段はナビゲーションとアクション、下段はタイトルを表示します。

Single/TwoRowTopAppBar関数以下はinternal/private修飾子付きの関数やプロパティなので、一般のユーザは扱うことができません。

スポンサーリンク

スクロールに連動した折り畳み

折り畳み動作

折り畳み動作のサンプル(LargeTopAppBarの例)です。

動作の様子が理解しやすいように、あえて、ゆっくりとリストをスワイプしています。

動作の様子は次のようになります。

 上にスワイプ 
  • (1)バーの高さが減る、リストはスクロールしない
  • (2)バーの高さが最小になると、リストのスクロールが始まる
 下にスワイプ 
  • (1)リストがスクロール、バーの高さは変わらない(最小のまま)
  • (2)リストの先頭が表示されると、バーの高さが増え始める
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LargeTopAppBarPanel() {
//    val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
//    val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState())
    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
    Scaffold(              // ↑↑ (0)ScrollBehaviorの作成 ↑↑
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        topBar = {		   // ↑↑ (2)Conectionの指定 ↑↑
            LargeTopAppBar(
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.primaryContainer,
                    titleContentColor = MaterialTheme.colorScheme.primary,
                ),
                title = { Text("Top app bar") },
                navigationIcon = {
                    IconButton(onClick = { /* クリック時の処理 */ }) {
                        Icon(
                            imageVector = Icons.Filled.ArrowBack,
                            contentDescription = "Back"
                        )
                    }
                },
                actions = {
                    IconButton(onClick = { /* クリック時の処理 */ }) {
                        Icon(
                            imageVector = Icons.Filled.Menu,
                            contentDescription = "Menu"
                        )
                    }
                },
                scrollBehavior = scrollBehavior				// (3)状態(バーの高さの変化)を通知
            )
        }
    ) { innerPadding ->
        Column(
            modifier = Modifier
                .padding(innerPadding)
                .verticalScroll(rememberScrollState()),		// (1)Dispatcherの指定
            verticalArrangement = Arrangement.spacedBy(16.dp),
        ) {
            for(i in 0..15) {
                Text(
                    modifier = Modifier.padding(start = 8.dp, end = 8.dp),
                    text = "スクロールアイテム(${i})"
                )
            }
        }
    }
}

NestedScroll(ネストスクロール)

TopAppBarの折り畳みは、「子UI(Column)の検出したスクロール(スワイプ)が親UI(Scaffold)に伝搬して、親UIが何かの挙動をスクロールに連動して起こす」動作です。

このような機能をNestedScroll(ネストスクロール)といいます。

Jetpack Composeにおいて、各UI要素の状態(表示内容)は引数を介して上位から下位階層へ伝搬させます。その逆に、イベントは下位から上位階層へ伝搬させて処理します。これが基本的なデータの流れです。

イベントの伝搬

スクロールはイベントですから、下位から上位階層へ伝搬させて処理することが基本です。

NestedScrollはこの基本的なデータの流れに従って機能を実現しています。

NestedScrollの構成

NestedScrollの機能を実現するために必要な要素は2つです。

 Dispatcher 

スクロール(スワイプ)を検出して、イベントを変化量へ変換した後に、親UIへ送ります。

リストの作成を目的にしたLazyリストはDispatcherをデフォルトで含みます。また、Columun/RowはModifier.verticalScroll/horizontalScroll修飾子の指定で、Dispatcherが組み込まれます。

 Connection 

子UIから受け取ったイベントの変化量をもとに、UIの新たな状態を作り出します。

TopAppBar用にScrollBehaviorが用意されています。この中に、ConnectionとUIの新たな状態に対するTopAppBarの振る舞い(折り畳みの様子)が定義されています。また、ScrollBehaviorは3つのタイプがあり、振る舞いが異なります。

ScrollBehaviorのタイプ

ScrollBehaviorのタイプの違いを示します。

pinnedScrollBehavior

enterAlwaysScrollBehavior

exitUntilCollapsedScrollBehavior

※折り畳み動作のサンプルで示した動画と同じ

スポンサーリンク

スクロールに連動したバー色

NestedScrollが設定されている場合、スクロールに連動したバー色の変更が可能です。

scrolledContainerColorを指定

スクロール中は引数(scrolledContainerColor)に指定された色になります。

    val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
    Scaffold(
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        topBar = {
            TopAppBar(
                colors = TopAppBarDefaults.topAppBarColors(
                    scrolledContainerColor = MaterialTheme.colorScheme.tertiaryContainer,
                    containerColor = MaterialTheme.colorScheme.primaryContainer,
                    titleContentColor = MaterialTheme.colorScheme.primary,
                ),
                title = { Text("Top app bar") },
                navigationIcon = { ... },
                actions = { ... },
                scrollBehavior = scrollBehavior
            )
        }
    ) { innerPadding -> ... }

コンテナ色がsurfaceの時

スクロール中はelevationに連動した影(透過する黒)が付きます。

    val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
    Scaffold(
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        topBar = {
            TopAppBar(
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.surface,
                    titleContentColor = MaterialTheme.colorScheme.primary,
                ),
                title = { Text("Top app bar") },
                navigationIcon = { ... },
                actions = { ... },
                scrollBehavior = scrollBehavior
            )
        }
    ) { innerPadding -> ... }
スポンサーリンク

影付きのバー

Viewシステムのアプリケーションバーは影が付いていました。しかし、Jetpack composeにおけるマテリアルデザインのアプリケーションバーは影が付きません。

必要であれば、Modifier修飾子を使って影を付けることが可能です。

            TopAppBar(
                modifier = Modifier.shadow(elevation = 10.dp),
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.primaryContainer,
                    titleContentColor = MaterialTheme.colorScheme.primary,
                ),
                title = { Text("Top app bar") },
                navigationIcon = { ... },
                actions = { ... },
                scrollBehavior = scrollBehavior
            )
			...

影付きのバー

スポンサーリンク

インセットの働き

インセットはステータスバーとアプリケーションバーの重なりを避ける働きをします。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            ScaffoldTheme {
                @OptIn(ExperimentalMaterial3Api::class)
                Scaffold(
                    modifier = Modifier.fillMaxSize(),
                    topBar = {
                        TopAppBar(
                            colors = TopAppBarDefaults.topAppBarColors(
                                containerColor = MaterialTheme.colorScheme.primaryContainer,
                                titleContentColor = MaterialTheme.colorScheme.primary,
                            ),
    //                        windowInsets = TopAppBarDefaults.windowInsets, // デフォルト
                            windowInsets = WindowInsets(0.dp, 0.dp, 0.dp, 0.dp),
                            title = { Text("Top app bar") },
                            navigationIcon = { ... },
                            actions = { ... },
                        )
                    }
                ) { innerPadding -> ... }
            }
        }
    }

インセットの働き

スポンサーリンク

関連記事:

Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のButtonについて、構成や使用方法などをまとめます。 ※環境:Android Studio Flamingo | 2022.2.1    :androidx.compose.material3:material3:1.1.1    :androidx.compose.ui:ui:1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSurfaceについて、構成や使用方法などをまとめます。 ※環境:Android Studio Flamingo | 2022.2.1    :androidx.compose.material3:material3:1.1.1    :androidx.compose.ui:ui:1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のRadioButtonについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1     Kotlin 1.8.10     Compose Compiler 1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中にUI要素を格納する機能をもつコンテナ型のUIがあります。 Column/Row/Boxがコンテナ型のUIです。構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 1     Kotlin 1.8.10     Compose Compiler 1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のImageについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation 1.5.0 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のDividerについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSpacerについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation 1.5.0 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSliderについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のScaffoldについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
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 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のFloatingActionButtonについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSnackbarについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のLazyColumnについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のLazyRowについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1 Patch 1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8 ...
スポンサーリンク