建構自動調整導覽功能

大多數應用程式都有一些頂層目的地,可透過應用程式的主要導覽 UI 存取。在精簡視窗 (例如標準手機螢幕) 中,目的地通常會顯示在視窗底部的導覽列中。在展開的視窗 (例如平板電腦上的全螢幕應用程式) 中,應用程式旁的導覽邊欄通常是更好的選擇,因為除了裝置的左側和右側,導覽控制項更容易觸及。

NavigationSuiteScaffold 可根據 WindowSizeClass 顯示適當的導覽 UI 可組合項,簡化導覽 UI 之間的切換。這包括在執行階段視窗大小變更期間以動態方式變更 UI。預設行為是顯示下列其中一個 UI 元件:

  • 導覽列:如果寬度或高度為密集,或裝置處於桌面型態
  • 其他用途的導覽邊欄
圖 1.NavigationSuiteScaffold 在精簡視窗中顯示導覽列。
圖 2.NavigationSuiteScaffold 會在展開的視窗中顯示導覽邊欄。

新增依附元件

NavigationSuiteScaffoldMaterial3 自動調整導覽套件程式庫的一部分。在應用程式或模組的 build.gradle 檔案中,新增程式庫的依附元件:

Kotlin


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

Groovy


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

建立 Scaffold

NavigationSuiteScaffold 的兩個主要部分是導覽套件項目和所選目的地的內容。您可以直接在可組合項中定義導覽套件項目,但通常必須在列舉部分定義這些導覽套件項目:

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.
}

在目的地內容 lambda 中,使用 currentDestination 值決定要顯示的 UI。如果您在應用程式中使用導覽程式庫,請在這裡使用這個程式庫顯示適當的目的地。when 陳述式可滿足這項條件:

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

變更色彩

NavigationSuiteScaffold 會在 Scaffold 佔用的整個區域 (通常是整個視窗) 建立 Surface。除此之外,鷹架會繪製特定導覽 UI,例如 NavigationBar。介面和導覽 UI 都會使用應用程式主題中指定的值,但您可以覆寫主題值。

containerColor 參數會指定表面的顏色。預設值為色彩配置的背景顏色。contentColor 參數會指定該介面「上」的內容顏色。預設值為 containerColor 所指定任何項目中的「上方」顏色。舉例來說,如果 containerColor 使用 background 顏色,則 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。不過,您可能會想要覆寫這個行為。舉例來說,如果應用程式針對動態消息顯示單一大型內容窗格,應用程式便可針對展開的視窗使用永久導覽導覽匣,但仍改回小型和中型視窗大小類別的預設行為:

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

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

其他資源

請參閱 Material Design 指南:

請參閱下列 androidx.compose.material3 程式庫元件: