Criar uma navegação adaptável

A maioria dos apps tem alguns destinos de nível superior que podem ser acessados pelo interface de navegação principal do app. Em janelas compactas, como um telefone padrão são exibidos, os destinos são normalmente exibidos em uma barra de navegação no parte inferior da janela. Em uma janela expandida, como um app de tela cheia em um tablet, uma coluna de navegação ao lado do app geralmente é a melhor opção, já que o os controles de navegação ficam mais fáceis de acessar ao segurar os lados esquerdo e direito do dispositivo.

O NavigationSuiteScaffold simplifica a troca entre as IUs de navegação, mostrando o elemento combinável da interface de navegação apropriada. com base em WindowSizeClass. Isso inclui recursos mudando a IU durante as mudanças no tamanho da janela do tempo de execução. O comportamento padrão é mostrar um dos seguintes componentes de IU:

  • Barra de navegação se a largura ou a altura for compacta ou se o dispositivo estiver postura de mesa
  • Coluna de navegação para todo o restante
Figura 1. NavigationSuiteScaffold mostra uma barra de navegação em janelas compactas.
Figura 2. O NavigationSuiteScaffold mostra uma coluna de navegação em janelas expandidas.

Adicionar dependências

NavigationSuiteScaffold faz parte do Pacote de navegação adaptável do Material 3 (link em inglês) biblioteca. Adicione uma dependência para a biblioteca no arquivo build.gradle do app. ou módulo:

Kotlin


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

Groovy


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

Criar um scaffold

As duas partes principais do NavigationSuiteScaffold são os itens do pacote de navegação. e o conteúdo do destino selecionado. É possível definir diretamente itens do pacote de navegação em um elemento combinável, mas é comum que eles sejam definidos em outro lugar, por exemplo, em um tipo enumerado:

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

Para usar NavigationSuiteScaffold, você precisa rastrear o destino atual, que você pode fazer usando rememberSaveable:

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

No exemplo a seguir, o parâmetro navigationSuiteItems (tipo NavigationSuiteScope usa a função item para definir a IU de navegação para um destino individual. A interface de destino é usados em barras de navegação, colunas e gavetas. Para criar itens de navegação, você Repita o AppDestinations (definido no snippet anterior):

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

Na lambda do conteúdo de destino, use o valor currentDestination para decidir qual interface exibir. Se você usa uma biblioteca de navegação no seu app, use-a aqui para exibir o destino apropriado. Uma instrução when pode ser suficiente:

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

Mudar de cor

NavigationSuiteScaffold cria uma Surface na área inteira. que o scaffold ocupa, normalmente a janela inteira. Além disso, o scaffold desenha a interface de navegação específica, como um NavigationBar. A plataforma e a interface de navegação usam os valores especificados no atributo mas é possível substituir os valores do tema.

O parâmetro containerColor especifica a cor da superfície. O padrão é a cor de fundo do seu esquema de cores. O parâmetro contentColor especifica a cor do conteúdo na plataforma. O padrão é "ativado". cor do que for especificado para containerColor. Por exemplo, se containerColor usa a cor background, e o contentColor usa a cor onBackground. Consulte Temas do Material Design 3 no Compose para mais detalhes sobre como funciona o sistema de cores. Ao substituir esses valores, use valores definidos no tema para que o app ofereça suporte à exibição clara e escura modos:

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

A interface de navegação é desenhada na frente da superfície NavigationSuiteScaffold. Os valores padrão das cores da interface são fornecidos pelo NavigationSuiteDefaults.colors(), mas você também podem substituir esses valores. Por exemplo, se você quer que o plano de fundo de que a barra de navegação seja transparente, mas os outros valores sejam o padrão, substituir navigationBarContainerColor:

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

Por fim, você pode personalizar cada item na interface de navegação. Ao chamar o método item, é possível transmitir em uma instância de NavigationSuiteItemColors A classe especifica as cores dos itens em uma barra, uma coluna e a navegação gaveta. Isso significa que é possível ter cores idênticas em cada tipo de interface de navegação, ou você pode variar as cores com base em suas necessidades. Defina as cores no Nível NavigationSuiteScaffold para usar a mesma instância de objeto para todos os itens e chamar a função NavigationSuiteDefaults.itemColors() para substituir apenas aqueles que você quer alterar:

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

Personalizar tipos de navegação

O comportamento padrão de NavigationSuiteScaffold muda a interface de navegação com base no tamanho da janela classes. No entanto, pode querer substituir esse comportamento. Por exemplo, se o app mostra um único grande painel de conteúdo para um feed, o aplicativo pode usar uma navegação permanente gaveta para janelas expandidas, mas ainda voltar ao comportamento padrão para classes de tamanho de janela compacta e média:

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

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

Outros recursos

Consulte as orientações do Material Design:

Confira os seguintes componentes da biblioteca androidx.compose.material3: