動的トップ アプリバーを作成する

このガイドでは、リストからアイテムが選択されたときにオプションが変更される動的なトップ アプリバーを Compose で作成する方法について説明します。選択状態に基づいて、トップ アプリバーのタイトルとアクションを変更できます。

動的なトップ アプリバーの動作を実装する

このコードは、アイテムの選択に基づいて変化するトップ アプリバーのコンポーズ可能な関数を定義します。

@Composable
fun AppBarSelectionActions(
    selectedItems: Set<Int>,
    modifier: Modifier = Modifier,
) {
    val hasSelection = selectedItems.isNotEmpty()
    val topBarText = if (hasSelection) {
        "Selected ${selectedItems.size} items"
    } else {
        "List of items"
    }

    TopAppBar(
        title = {
            Text(topBarText)
        },
        colors = TopAppBarDefaults.topAppBarColors(
            containerColor = MaterialTheme.colorScheme.primaryContainer,
            titleContentColor = MaterialTheme.colorScheme.primary,
        ),
        actions = {
            if (hasSelection) {
                IconButton(onClick = {
                    /* click action */
                }) {
                    Icon(
                        imageVector = Icons.Filled.Share,
                        contentDescription = "Share items"
                    )
                }
            }
        },
        modifier = modifier
    )
}

コードに関する主なポイント

  • AppBarSelectionActions は、選択されたアイテム インデックスの Set を受け入れます。
  • topBarText は、アイテムを選択するかどうかによって変わります。
    • アイテムを選択すると、選択したアイテムの数を示すテキストが TopAppBar に表示されます。
    • アイテムを選択しない場合、topBarText は「アイテムのリスト」になります。
  • actions ブロックは、トップアプリバーに表示するアクションを定義します。hasSelection が true の場合、テキストの後に共有アイコンが表示されます。
  • IconButton の onClick ラムダは、アイコンをクリックしたときに共有アクションを処理します。

結果

動的なトップ アプリバーに、共有アイコンとともに「3 個のアイテムを選択しました」というテキストが表示されています。このテキストとアイコンは、アイテムが選択されている場合にのみ表示されます。
図 1. アイテムが選択されたときにのみ表示されるテキストと共有アイコンを含む動的なトップアプリバー。

選択可能なリストを動的な上部アプリバーに統合する

次の例は、選択可能なリストを動的なトップ アプリバーに追加する方法を示しています。

@Composable
private fun AppBarMultiSelectionExample(
    modifier: Modifier = Modifier,
) {
    val listItems by remember { mutableStateOf(listOf(1, 2, 3, 4, 5, 6)) }
    var selectedItems by rememberSaveable { mutableStateOf(setOf<Int>()) }

    Scaffold(
        modifier = modifier,
        topBar = { AppBarSelectionActions(selectedItems) }
    ) { innerPadding ->
        LazyColumn(contentPadding = innerPadding) {
            itemsIndexed(listItems) { _, index ->
                val isItemSelected = selectedItems.contains(index)
                ListItemSelectable(
                    selected = isItemSelected,
                    Modifier
                        .combinedClickable(
                            interactionSource = remember { MutableInteractionSource() },
                            indication = null,
                            onClick = {
                                /* click action */
                            },
                            onLongClick = {
                                if (isItemSelected) selectedItems -= index else selectedItems += index
                            }
                        )
                )
            }
        }
    }
}

コードに関する主なポイント

  • 選択したリストアイテムの数に応じて、上部のバーが更新されます。
  • selectedItems には、選択されたアイテムのインデックスのセットが保持されます。
  • AppBarMultiSelectionExample は、Scaffold を使用して画面を構造化します。
    • topBar = { AppBarSelectionActions(selectedItems) } は、AppBarSelectionActions コンポーザブルをトップ アプリバーとして設定します。AppBarSelectionActions は selectedItems 状態を受け取ります。
  • LazyColumn は、アイテムを縦方向のリストに表示し、画面に表示されているアイテムのみをレンダリングします。
  • ListItemSelectable は、選択可能なリストアイテムを表します。
    • combinedClickable では、アイテムの選択に対してクリックと長押しを処理できます。クリックするとアクションが実行され、アイテムを長押しすると選択状態が切り替わります。

結果

動的なトップアプリバーに「3 個のアイテムを選択しました」というテキストが表示され、その後に共有アイコンが表示されています。下には、いくつかの項目がリスト表示されており、選択された 3 つの項目の横にチェックマークが付いています。
図 2. 特定のアイテムが選択された、動的なトップアプリバーに統合されたリスト。

参考情報