Adaptive Navigation erstellen

Die meisten Anwendungen haben einige Ziele auf oberster Ebene, auf die über die primäre Navigations-UI der App zugegriffen werden kann. In kompakten Fenstern, z. B. auf dem Standarddisplay eines Smartphones, werden die Ziele in der Regel in einer Navigationsleiste unten im Fenster angezeigt. In einem erweiterten Fenster, z. B. einer Vollbild-App auf einem Tablet, ist eine Navigationsleiste neben der App in der Regel eine bessere Wahl, da die Navigationssteuerelemente einfacher erreichbar sind, wenn sie die linke und rechte Seite des Geräts halten.

NavigationSuiteScaffold vereinfacht den Wechsel zwischen Navigations-UIs, da die entsprechende zusammensetzbare Navigations-UI basierend auf WindowSizeClass angezeigt wird. Dazu gehört auch das dynamische Ändern der UI bei Änderungen der Laufzeitfenstergröße. Standardmäßig wird eine der folgenden UI-Komponenten angezeigt:

  • Navigationsleiste, wenn die Breite oder Höhe kompakt ist oder das Gerät auf dem Tisch steht
  • Navigationsleiste für alles andere
Abbildung 1. NavigationSuiteScaffold zeigt eine Navigationsleiste in kompakten Fenstern an.
Abbildung 2. NavigationSuiteScaffold zeigt eine Navigationsleiste in maximierten Fenstern an.

Abhängigkeiten hinzufügen

NavigationSuiteScaffold ist Teil der Bibliothek Adaptive Navigation Suite von Material3. Fügen Sie in der Datei build.gradle Ihrer App oder Ihres Moduls eine Abhängigkeit für die Bibliothek hinzu:

Kotlin


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

Groovig


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

Gerüst erstellen

Die beiden Hauptteile von NavigationSuiteScaffold sind die Elemente der Navigationssuite und der Inhalt für das ausgewählte Ziel. Sie können die Elemente der Navigationssuite direkt in einer zusammensetzbaren Funktion definieren. Es ist jedoch üblich, sie an anderer Stelle zu definieren, z. B. in einer Enum:

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),
}

Wenn Sie NavigationSuiteScaffold verwenden möchten, müssen Sie das aktuelle Ziel erfassen. Dazu können Sie rememberSaveable verwenden:

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

Im folgenden Beispiel definiert der Parameter navigationSuiteItems (Typ NavigationSuiteScope) mithilfe seiner Funktion item die Navigations-UI für ein einzelnes Ziel. Die Ziel-UI wird für Navigationsleisten, Schienen und Leisten verwendet. Zum Erstellen von Navigationselementen führen Sie eine Schleife durch Ihr AppDestinations-Element, das im vorherigen Snippet definiert wurde:

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

Entscheiden Sie in der Lambda-Funktion für Zielinhalt mit dem Wert currentDestination, welche UI angezeigt werden soll. Wenn Sie in Ihrer App eine Navigationsbibliothek verwenden, verwenden Sie sie hier, um das entsprechende Ziel anzuzeigen. Eine „Wann“-Anweisung kann ausreichen:

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

Farben ändern

NavigationSuiteScaffold erstellt ein Surface, das den gesamten Bereich einnimmt, den das Gerüst einnimmt, in der Regel das gesamte Fenster. Darüber hinaus zeichnet das Gerüst die jeweilige Navigations-UI, z. B. NavigationBar. Sowohl für die Oberfläche als auch für die Navigations-UI werden die Werte verwendet, die im Design Ihrer App angegeben sind. Sie können die Themenwerte aber überschreiben.

Der Parameter containerColor gibt die Farbe der Oberfläche an. Die Standardeinstellung ist die Hintergrundfarbe Ihres Farbschemas. Der Parameter contentColor gibt die Farbe der Inhalte auf dieser Oberfläche an. Der Standardwert ist die „An“-Farbe des für containerColor angegebenen Werts. Wenn containerColor beispielsweise die Farbe background verwendet, verwendet contentColor die Farbe onBackground. Weitere Informationen zur Funktionsweise des Farbsystems finden Sie unter Material Design 3-Designs in Compose. Wenn Sie diese Werte überschreiben, verwenden Sie im Design definierte Werte, damit Ihre App dunkle und helle Anzeigemodi unterstützt:

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

Die Navigations-UI wird vor der NavigationSuiteScaffold-Oberfläche gezeichnet. Die Standardwerte für die Farben der Benutzeroberfläche werden von NavigationSuiteDefaults.colors() bereitgestellt. Sie können diese Werte jedoch auch überschreiben. Wenn beispielsweise der Hintergrund der Navigationsleiste transparent sein soll, die anderen Werte jedoch die Standardwerte sein sollen, überschreiben Sie navigationBarContainerColor:

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

Letztendlich können Sie jedes Element in der Navigations-UI anpassen. Wenn Sie die Funktion item aufrufen, können Sie eine Instanz von NavigationSuiteItemColors übergeben. Die Klasse gibt die Farben für Elemente in einer Navigationsleiste, einer Navigationsleiste und einer Navigationsleiste an. Das bedeutet, dass Sie für jeden Navigations-UI-Typ identische Farben verwenden oder die Farben je nach Bedarf variieren können. Definieren Sie die Farben auf NavigationSuiteScaffold-Ebene, um für alle Elemente dieselbe Objektinstanz zu verwenden, und rufen Sie die Funktion NavigationSuiteDefaults.itemColors() auf, um nur die Farben zu überschreiben, die Sie ändern möchten:

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

Navigationstypen anpassen

Durch das Standardverhalten von NavigationSuiteScaffold wird die Navigations-UI basierend auf Fenstergrößenklassen geändert. Möglicherweise möchten Sie dieses Verhalten jedoch überschreiben. Wenn Ihre App beispielsweise einen einzelnen großen Inhaltsbereich für einen Feed anzeigt, könnte sie eine permanente Navigationsleiste für maximierte Fenster verwenden und dennoch auf das Standardverhalten für Klassen mit kompakten und mittelgroßen Fenstern zurückgreifen:

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

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

Weitere Informationen

Weitere Informationen finden Sie in den Material Design-Anleitungen:

Siehe die folgenden Komponenten der androidx.compose.material3-Bibliothek: