アダプティブ ナビゲーションを作成する

ほとんどのアプリには、アプリのプライマリ ナビゲーション UI からアクセスできるトップレベル デスティネーションがいくつかあります。標準のスマートフォンのディスプレイなどのコンパクトなウィンドウでは、通常、デスティネーションはウィンドウの下部にあるナビゲーション バーに表示されます。タブレットの全画面表示アプリなどの拡大ウィンドウでは、デバイスの左右を手に持ったときにナビゲーション コントロールに簡単にアクセスできるため、通常はアプリの横にナビゲーション レールを配置することをおすすめします。

NavigationSuiteScaffold は、WindowSizeClass に基づいて適切なナビゲーション UI コンポーザブルを表示することで、ナビゲーション UI の切り替えを簡素化します。これには、ランタイム ウィンドウ サイズが変更されたときの UI の動的な変更が含まれます。デフォルトの動作では、次のいずれかの UI コンポーネントが表示されます。

  • ナビゲーション バー: 幅または高さがコンパクトの場合、またはデバイスがテーブルトップ形状の場合
  • ナビゲーション レール: その他すべてに使用
図 1.NavigationSuiteScaffold は、ナビゲーション バーをコンパクト ウィンドウに表示します。
図 2.NavigationSuiteScaffold は、開いたウィンドウにナビゲーション レールを表示します。

依存関係を追加する

NavigationSuiteScaffold は、Material3 アダプティブ ナビゲーション スイート ライブラリの一部です。アプリまたはモジュールの build.gradle ファイルにライブラリの依存関係を追加します。

Kotlin


implementation("androidx.compose.material3:material3-adaptive-navigation-suite")

Groovy


implementation 'androidx.compose.material3:material3-adaptive-navigation-suite'

スキャフォールドを作成する

NavigationSuiteScaffold の 2 つの主要部分は、ナビゲーション スイートのアイテムと、選択されたデスティネーションのコンテンツです。ナビゲーション スイートのアイテムはコンポーザブルで直接定義できますが、これらは別の場所(列挙型など)で定義するのが一般的です。

enum class AppDestinations(
    @StringRes val label: Int,
    val icon: ImageVector,
    @StringRes val contentDescription: Int
) {
    HOME(R.string.home, Icons.Default.Home, R.string.home),
    FAVORITES(R.string.favorites, Icons.Default.Favorite, R.string.favorites),
    SHOPPING(R.string.shopping, Icons.Default.ShoppingCart, R.string.shopping),
    PROFILE(R.string.profile, Icons.Default.AccountBox, R.string.profile),
}

NavigationSuiteScaffold を使用するには、現在のデスティネーションを追跡する必要があります。これを行うには、rememberSaveable を使用します。

var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }

次の例では、navigationSuiteItems パラメータ(タイプ NavigationSuiteScope)で item 関数を使用して、個々のデスティネーションのナビゲーション UI を定義しています。デスティネーション UI は、ナビゲーション バー、レール、ドロワー全体で使用されます。ナビゲーション アイテムを作成するには、AppDestinations(上記のスニペットで定義)をループします。

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it }
            )
        }
    }
) {
    // TODO: Destination content.
}

デスティネーション コンテンツ ラムダ内で、currentDestination 値を使用して、表示する UI を決定します。アプリでナビゲーション ライブラリを使用する場合は、ここでそれを使用して、適切なデスティネーションを表示します。when ステートメントは以下の要件を満たします。

NavigationSuiteScaffold(
    navigationSuiteItems = { /*...*/ }
) {
    // Destination content.
    when (currentDestination) {
        AppDestinations.HOME -> HomeDestination()
        AppDestinations.FAVORITES -> FavoritesDestination()
        AppDestinations.SHOPPING -> ShoppingDestination()
        AppDestinations.PROFILE -> ProfileDestination()
    }
}

色を変更

NavigationSuiteScaffold は、スキャフォールドが占有する領域全体(通常はウィンドウ全体)に Surface を作成します。その上に、スキャフォールドは NavigationBar などの特定のナビゲーション UI を描画します。サーフェス UI とナビゲーション UI の両方で、アプリのテーマで指定された値が使用されますが、テーマの値をオーバーライドできます。

containerColor パラメータは、サーフェスの色を指定します。デフォルトはカラーパターンの背景色です。contentColor パラメータは、そのサーフェス上のコンテンツの色を指定します。デフォルトでは、containerColor に指定された「オン」の色です。たとえば、containerColorbackground 色が使用されている場合、contentColor では onBackground 色が使用されます。カラーシステムの仕組みについて詳しくは、Compose のマテリアル デザイン 3 テーマ設定をご覧ください。これらの値をオーバーライドするときは、アプリがダークとライトの表示モードをサポートするように、テーマで定義された値を使用します。

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    containerColor = MaterialTheme.colorScheme.primary,
    contentColor = MaterialTheme.colorScheme.onPrimary,
) {
    // Content...
}

ナビゲーション UI は、NavigationSuiteScaffold サーフェスの前に描画されます。UI の色のデフォルト値は NavigationSuiteDefaults.colors() によって指定されますが、これらの値をオーバーライドすることもできます。たとえば、ナビゲーション バーの背景を透明にして他の値をデフォルトにする場合は、navigationBarContainerColor をオーバーライドします。

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    navigationSuiteColors = NavigationSuiteDefaults.colors(
        navigationBarContainerColor = Color.Transparent,
    )
) {
    // Content...
}

最終的には、ナビゲーション UI の各項目をカスタマイズできます。item 関数を呼び出すときに、NavigationSuiteItemColors のインスタンスを渡すことができます。このクラスでは、ナビゲーション バー、ナビゲーション レール、ナビゲーション ドロワーのアイテムの色を指定します。つまり、ナビゲーション UI タイプごとに同じ色を使用することも、ニーズに応じて色を変えることもできます。すべてのアイテムに同じオブジェクト インスタンスを使用するように NavigationSuiteScaffold レベルで色を定義し、NavigationSuiteDefaults.itemColors() 関数を呼び出して変更する色のみをオーバーライドします。

val myNavigationSuiteItemColors = NavigationSuiteDefaults.itemColors(
    navigationBarItemColors = NavigationBarItemDefaults.colors(
        indicatorColor = MaterialTheme.colorScheme.primaryContainer,
        selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer
    ),
)

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it },
                colors = myNavigationSuiteItemColors,
            )
        }
    },
) {
    // Content...
}

ナビゲーション タイプをカスタマイズする

NavigationSuiteScaffold のデフォルトの動作では、ウィンドウ サイズクラスに基づいてナビゲーション UI が変更されます。ただし、この動作をオーバーライドすることをおすすめします。たとえば、フィードで 1 つの大きなコンテンツペインを表示するアプリの場合、開いたウィンドウには固定的なナビゲーション ドロワーを使用できますが、コンパクトなウィンドウ サイズクラスと中程度のウィンドウ サイズクラスでは、デフォルトの動作にフォールバックできます。

val adaptiveInfo = currentWindowAdaptiveInfo()
val customNavSuiteType = with(adaptiveInfo) {
    if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.EXPANDED) {
        NavigationSuiteType.NavigationDrawer
    } else {
        NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo)
    }
}

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    layoutType = customNavSuiteType,
) {
    // Content...
}

参考情報

以下のマテリアル デザイン ガイダンスをご覧ください。

以下の androidx.compose.material3 ライブラリ コンポーネントをご覧ください。