3
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?

AppBarRow/AppBarColumnによるAdaptiveなボタン配置

Posted at

Compose Material3 1.4.0 から AppBarRow / AppBarColumn というオーバーフローした時に自動で省略してくれる API が追加されました。これを使うことでアクションの配置の Adaptive 対応がしやすくなります。

ezgif-6aeeca75c7ca8b.gif

実装

AppBarRow / AppBarColumn は以下のようなシンプルな引数になっています。

  • overflowIndicator は Menu アイコンを表示する Slot
  • maxItemCount はアイテムの最大表示数
    • デフォルトの場合は画面に収まりきるまでの最大数を表示
  • AppBarRowScope / AppBarColumnScope では以下の 3 パターンのアイテムが設定可能
    • clickableItem
    • toggleableItem
    • customItem
fun AppBarRow(
    overflowIndicator: @Composable (AppBarMenuState) -> Unit,
    modifier: Modifier = Modifier,
    maxItemCount: Int = Int.MAX_VALUE,
    content: AppBarRowScope.() -> Unit,
)

fun AppBarColumn(
    overflowIndicator: @Composable (AppBarMenuState) -> Unit,
    modifier: Modifier = Modifier,
    maxItemCount: Int = Int.MAX_VALUE,
    content: AppBarColumnScope.() -> Unit,
)

maxItemCount を画面サイズで変えることによって Adaptive な表示にすることができます。

val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
val maxItemCount = if (windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND)) {
    5
} else {
    3
}
AppBarRow(
    maxItemCount = maxItemCount,
    overflowIndicator = {
        ...
    },
) {
    ...
}
Phone Tablet
image.png image.png

この AppBarRow / AppBarColumnTopAppBarFloatingToolbar に使うことでアクションの配置を省略してくれるようになります。

AppBar(TopAppBar) で使う場合

TopAppBar(
    title = {
        Text("Title", maxLines = 1, overflow = TextOverflow.Ellipsis)
    },
    navigationIcon = {
        IconButton(
            onClick = { ... }
        ) {
            Icon(
                painterResource(R.drawable.ic_arrow_back),
                contentDescription = "Back",
            )
        }
    },
    actions = {
        val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
        val maxItemCount =
            if (windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND)) {
                5
            } else {
                3
            }
        AppBarRow(
            maxItemCount = maxItemCount,
            overflowIndicator = { menuState ->
                IconButton(onClick = { menuState.show() }) {
                    Icon(
                        painterResource(R.drawable.ic_more_vert),
                        contentDescription = "Other options",
                    )
                }
            },
        ) {
            clickableItem(
                onClick = { ... },
                icon = {
                    Icon(
                        painterResource(R.drawable.ic_search),
                        contentDescription = null,
                    )
                },
                label = "Search",
            )
        
            toggleableItem(
                checked = isFavorited,
                onCheckedChange = {
                    isFavorited = !isFavorited
                },
                icon = {
                    Icon(
                        painterResource(
                            if (isFavorited) {
                                R.drawable.ic_favorite_filled
                            } else {
                                R.drawable.ic_favorite
                            }
                        ),
                        contentDescription = null,
                    )
                },
                label = if (isFavorited) {
                    "Remove from favotites"
                } else {
                    "Add to favorites"
                },
            )

            ...
        }
    },
)

FloatingToolbar で使う場合

HorizontalFloatingToolbar(
    modifier = Modifier.align(Alignment.BottomCenter).offset(y = -FloatingToolbarDefaults.ScreenOffset),
    expanded = true,
    leadingContent = { ... },
    trailingContent = {
        AppBarRow(
            overflowIndicator = { menuState ->
                IconButton(onClick = { menuState.show() }) {
                    Icon(
                        painterResource(R.drawable.ic_more_vert),
                        contentDescription = "Other options",
                    )
                }
            },
        ) {
            clickableItem(
                onClick = { ... },
                icon = {
                    Icon(
                        painterResource(R.drawable.ic_arrow_back),
                        contentDescription = null,
                    )
                },
                label = "Back",
            )

            clickableItem(
                onClick = { ... },
                icon = {
                    Icon(
                        painterResource(R.drawable.ic_arrow_forward),
                        contentDescription = null,
                    )
                },
                label = "Forward",
            )

            toggleableItem(
                checked = isFavorited,
                onCheckedChange = {
                    isFavorited = !isFavorited
                },
                icon = {
                    Icon(
                        painterResource(
                            if (isFavorited) {
                                R.drawable.ic_favorite_filled
                            } else {
                                R.drawable.ic_favorite
                            }
                        ),
                        contentDescription = null,
                    )
                },
                label = if (isFavorited) {
                    "Remove from favotites"
                } else {
                    "Add to favorites"
                },
            )
            ...
        }
    },
    content = {
        FilledIconButton(
            modifier = Modifier.width(64.dp),
            onClick = { ... }
        ) {
            Icon(painterResource(R.drawable.ic_add), contentDescription = "Add")
        }
    }
)
3
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
3
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?