Creare una navigazione adattiva

La maggior parte delle app ha alcune destinazioni di primo livello accessibili tramite alla UI di navigazione principale dell'app. In finestre compatte, come i telefoni standard Display, le destinazioni vengono solitamente visualizzate in una barra di navigazione al nella parte inferiore della finestra. In una finestra espansa, ad esempio un'app a schermo intero su una tablet, una barra di navigazione accanto all'app è solitamente una scelta migliore poiché i controlli di navigazione sono più facili da raggiungere tenendo premuti i lati sinistro e destro del dispositivo.

NavigationSuiteScaffold semplifica il passaggio da una UI di navigazione all'altra mostrando l'apposita UI di navigazione componibile in base a WindowSizeClass. Questo include in modo dinamico la modifica dell'interfaccia utente durante le modifiche alle dimensioni della finestra di runtime. Il comportamento predefinito è mostra uno dei seguenti componenti dell'interfaccia utente:

  • Barra di navigazione se la larghezza o l'altezza sono compatte o se il dispositivo è in postura da tavolo
  • Barra di navigazione per tutto il resto
Figura 1. NavigationSuiteScaffold mostra una barra di navigazione in finestre compatte.
.
.
Figura 2. NavigationSuiteScaffold mostra una barra di navigazione nelle finestre espanse.

Aggiungi dipendenze

NavigationSuiteScaffold fa parte di Suite di navigazione adattiva Material3 libreria. Aggiungi una dipendenza per la libreria nel file build.gradle della tua app o modulo:

Kotlin


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

Alla moda


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

Crea uno scaffold

Le due parti principali di NavigationSuiteScaffold sono gli elementi della suite di navigazione e i contenuti per la destinazione selezionata. Puoi definire direttamente degli elementi della suite di navigazione in un componibile, ma è normale che siano definiti altrove, ad esempio in un'enumerazione:

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

Per utilizzare NavigationSuiteScaffold, devi monitorare la destinazione corrente, che che puoi fare utilizzando rememberSaveable:

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

Nell'esempio seguente, il parametro navigationSuiteItems (type NavigationSuiteScope utilizza la funzione item per definire la UI di navigazione per una singola destinazione. L'interfaccia utente di destinazione utilizzati in barre di navigazione, guide e riquadri a scomparsa. Per creare elementi di navigazione, Esegui il loop su AppDestinations (definito nello snippet precedente):

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

All'interno del lambda dei contenuti di destinazione, utilizza il valore currentDestination per per decidere quale UI visualizzare. Se usi una libreria di navigazione nella tua app, usala. qui per visualizzare la destinazione appropriata. Un'affermazione "quando" può essere sufficiente:

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

Cambia colori

NavigationSuiteScaffold crea una Surface sull'intera area che l'impalcatura occupa, di solito l'intera finestra. Inoltre, l'impalcatura consente di disegnare una determinata UI di navigazione, ad esempio NavigationBar. Sia la piattaforma che la UI di navigazione utilizzano i valori specificati nella tema, ma puoi sostituire i valori del tema.

Il parametro containerColor specifica il colore della superficie. Il valore predefinito è il colore di sfondo della combinazione di colori. Il parametro contentColor specifica il colore dei contenuti su quella superficie. L'impostazione predefinita è "on" colore di qualsiasi valore specificato per containerColor. Ad esempio, se containerColor usa il colore background, dopodiché contentColor usa il colore onBackground. Vedi Temi di Material Design 3 in Compose per ulteriori dettagli sul funzionamento del sistema di colori. Quando esegui l'override di questi valori, Utilizza i valori definiti nel tema in modo che la tua app supporti il display chiaro e scuro modalità:

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

L'UI di navigazione è disegnata di fronte alla superficie NavigationSuiteScaffold. I valori predefiniti per i colori dell'interfaccia utente sono forniti da NavigationSuiteDefaults.colors(), ma tu possono sostituire questi valori. Ad esempio, se vuoi che lo sfondo barra di navigazione in modo che sia trasparente, ma gli altri valori siano i valori predefiniti, sostituisci navigationBarContainerColor:

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

In definitiva, puoi personalizzare ogni elemento nell'interfaccia utente di navigazione. Quando chiami il metodo item, puoi passare in un'istanza di NavigationSuiteItemColors. La classe specifica i colori degli elementi in una barra di navigazione, in una barra di navigazione e in una barra di navigazione riquadro a scomparsa. Ciò significa che puoi avere colori identici per ogni tipo di UI di navigazione, oppure variare i colori in base alle esigenze. Definisci i colori nella Livello di NavigationSuiteScaffold per utilizzare la stessa istanza dell'oggetto per tutti gli elementi e richiamare la funzione NavigationSuiteDefaults.itemColors() solo per eseguire l'override quelle da modificare:

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

Personalizza i tipi di navigazione

Il comportamento predefinito di NavigationSuiteScaffold modifica l'UI di navigazione in base alle dimensioni della finestra classi. Tuttavia, potresti voler ignorare questo comportamento. Ad esempio, se la tua app mostra una singola un grande riquadro di contenuti per un feed, l'app potrebbe utilizzare una navigazione permanente riquadro a scomparsa per le finestre espanse, ma ripristinare comunque il comportamento predefinito per per le classi di dimensioni delle finestre compatte e medie:

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

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

Risorse aggiuntive

Consulta le indicazioni relative a Material Design:

Vedi i seguenti componenti della libreria androidx.compose.material3: