1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Material 3 Expressive実装例 : App bar

Last updated at Posted at 2025-06-11

Material 3 Expressive の実装例の紹介シリーズです。
今回は App bar 系を紹介します。
(androidx.compose.material3:material3:1.4.0-alpha15 時点での内容になります。)

Material 3 Expressive での変更点

  • Top app bar から App bar にリネーム
  • Search app bar の追加
  • Material 3 で追加された Medium と Large の TopAppBar が廃止され、新たに Medium flexible と Large flexible の App bar が追加

実装

Small app bar

TopAppBar に title や subtitle、navigationIcon、 actions 等が Slot として用意されています。

TopAppBar(
    title = {
        Text("Title", maxLines = 1, overflow = TextOverflow.Ellipsis)
    }
)

// with subtitle
TopAppBar(
    title = {
        Text("Title", maxLines = 1, overflow = TextOverflow.Ellipsis)
    },
    subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
)

// with actions
TopAppBar(
    title = {
        Text("Title", maxLines = 1, overflow = TextOverflow.Ellipsis)
    },
    subtitle = { 
        Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) 
    },
    navigationIcon = {
        IconButton(onClick = {}) {
            Icon(...)
        }
    },
    actions = {
        IconButton(onClick = {}) {
            Icon(...)
        }
    }
)

// Center aligned
CenterAlignedTopAppBar(
    title = {
        Text("Title", maxLines = 1, overflow = TextOverflow.Ellipsis)
    },
    navigationIcon = {
        IconButton(onClick = {}) { ... }
    },
    actions = {
        IconButton(onClick = {}) { ... }
    }
)

// Center aligned with subtitle
TopAppBar(
    title = {
        Text("Title", maxLines = 1, overflow = TextOverflow.Ellipsis)
    },
    subtitle = { 
        Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) 
    },
    titleHorizontalAlignment = Alignment.CenterHorizontally,
    navigationIcon = {
        IconButton(onClick = {}) { ... }
    },
    actions = {
        IconButton(onClick = {}) { ... }
    }
)

Medium flexible app bar

MediumFlexibleTopAppBar を使います。基本的には TopAppBar の使い方と同じになっています。

val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        MediumFlexibleTopAppBar(
            title = {
                Text("Title", maxLines = 1, overflow = TextOverflow.Ellipsis)
            },
            subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            navigationIcon = { ... },
            actions = { ... },
            scrollBehavior = scrollBehavior
        )
    },
) { ... }

Large flexible app bar

LargeFlexibleTopAppBar を使います。こちらも基本的には TopAppBar の使い方と同じになっています。

val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        LargeFlexibleTopAppBar(
            title = {
                Text("Title", maxLines = 1, overflow = TextOverflow.Ellipsis)
            },
            subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
            navigationIcon = { ... },
            actions = { ... },
            scrollBehavior = scrollBehavior
        )
    },
) { ... }

App bar + Adaptive actions

App bar の action 部分に AppBarRow / AppBarColumn を使うことで、画面サイズで action のアイテムを自動で省略する実装ができます。

App bar の action のアイテム数は Compact の時は最大 2 つまでに留め、それ以上の場合は Toolbar を検討しましょう。
Toolbar の配置が困難な場合に AppBarRow / AppBarColumn で省略するようにしましょう。
https://m3.material.io/components/app-bars/guidelines#224e8ca0-4177-45f4-9f4f-eef1fbb0e4b2

val sizeClass = currentWindowAdaptiveInfo().windowSizeClass
val maxItemCount = if (sizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND)) {
    5
} else {
    3
}
TopAppBar(
    title = {
        Text("Title", maxLines = 1, overflow = TextOverflow.Ellipsis)
    },
    actions = {
        AppBarRow(
            maxItemCount = maxItemCount,
            overflowIndicator = {
                IconButton(onClick = { it.show() }) {
                    Icon(
                        painter = painterResource(R.drawable.ic_more),
                        contentDescription = "Other options"
                    )
                }
            }
        ) {
            clickableItem(
                onClick = {},
                icon = {
                    Icon(
                        painter = painterResource(R.drawable.ic_add),
                        contentDescription = null
                    )
                },
                label = "Create"
            )
    
            clickableItem(
                onClick = {},
                icon = {
                    Icon(
                        painter = painterResource(R.drawable.ic_star),
                        contentDescription = null
                    )
                },
                label = "Favorites"
            )
    
            clickableItem(
                onClick = {},
                icon = {
                    Icon(
                        painter = painterResource(R.drawable.ic_search),
                        contentDescription = null
                    )
                },
                label = "Search"
            )
    
            clickableItem(
                onClick = {},
                icon = {
                    Icon(
                        painter = painterResource(R.drawable.ic_settings),
                        contentDescription = null
                    )
                },
                label = "Settings"
            )
        }
    }
}
Compact Medium
Screenshot_20250609_101107.png Screenshot_20250609_101116.png

Search app bar

ガイドラインに記載されているような見た目の Search app bar の標準の実装はなく、現時点では SearchBar をカスタムする形になります。
追加され次第追記します。

TwoRowsTopAppBar によるカスタマイズ

MediumFlexibleTopAppBarLargeFlexibleTopAppBarTwoRowsTopAppBar の上に実装されており、元となる TwoRowsTopAppBar を使うことで自由な Flexible app bar を実装することができます。
引数で collapsedHeightexpandedHeight のサイズを指定すれば固定の高さに、未指定であればコンテンツの高さになります。

val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
TwoRowsTopAppBar(
    title = { expanded ->
        if (expanded) {
            Text("Expanded TopAppBar\nWith two lines")
        } else {
            Text("Collapsed TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
        }
    },
    subtitle = { expanded ->
        if (expanded) {
            Text(
                "Expanded Subtitle",
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
                modifier = Modifier.padding(bottom = 24.dp)
            )
        } else {
            Text("Collapsed Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis)
        }
    },
    navigationIcon = { ... },
    scrollBehavior = scrollBehavior
)    
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?