Detalhes e listas é um padrão de interface que consiste em um layout de painel duplo, em que um painel apresenta uma lista de itens e o outro mostra os detalhes dos itens selecionados na lista.
O padrão é particularmente útil para aplicativos que fornecem informações detalhadas sobre elementos de grandes coleções, por exemplo, um cliente de e-mail que tem uma lista de e-mails e o conteúdo detalhado de cada mensagem. O layout de detalhes e listas também pode ser usado para caminhos menos críticos, como dividir as preferências do app em uma lista de categorias com as preferências de cada categoria no painel de detalhes.
Implementar o padrão de detalhes e listas com NavigableListDetailPaneScaffold
NavigableListDetailPaneScaffold é um elemento combinável que simplifica a implementação de um
layout de detalhes e listas no Jetpack Compose. Ele envolve ListDetailPaneScaffold e
adiciona navegação integrada e animações de volta preditiva.
Um scaffold de detalhes e listas oferece suporte a até três painéis:
- Painel de lista: mostra uma coleção de itens.
- Painel de detalhes: mostra os detalhes de um item selecionado.
- Painel extra (opcional): fornece mais contexto quando necessário.
O scaffold se adapta com base no tamanho da janela:
- Em janelas grandes, os painéis de lista e de detalhes aparecem lado a lado.
- Em janelas pequenas, apenas um painel fica visível por vez, alternando conforme os usuários navegam.
Declarar dependências
NavigableListDetailPaneScaffold faz parte da biblioteca de navegação adaptativa do Material 3.
Adicione as três dependências relacionadas abaixo ao arquivo build.gradle do seu
app ou módulo:
Kotlin
implementation("androidx.compose.material3.adaptive:adaptive") implementation("androidx.compose.material3.adaptive:adaptive-layout") implementation("androidx.compose.material3.adaptive:adaptive-navigation")
Groovy
implementation 'androidx.compose.material3.adaptive:adaptive' implementation 'androidx.compose.material3.adaptive:adaptive-layout' implementation 'androidx.compose.material3.adaptive:adaptive-navigation'
- adaptável: elementos básicos de baixo nível, como
HingeInfoePosture. - adaptive-layout: layouts adaptáveis, como
ListDetailPaneScaffoldeSupportingPaneScaffold - adaptive-navigation: elementos combináveis para navegar dentro e entre painéis,
além de layouts adaptáveis que oferecem suporte à navegação por padrão, como
NavigableListDetailPaneScaffoldeNavigableSupportingPaneScaffold.
Verifique se o projeto inclui a versão 1.1.0-beta1 do compose-material3-adaptive ou mais recente.
Ativar o gesto de volta preditivo
Para ativar as animações de volta preditiva no Android 15 ou versões anteriores, é necessário ativar
o gesto de volta preditivo. Para ativar, adicione
android:enableOnBackInvokedCallback="true" à tag <application> ou
a tags <activity> individuais no arquivo AndroidManifest.xml. Para mais
informações, consulte Ativar o gesto de volta preditivo.
Quando o app segmentar o Android 16 (nível 36 da API) ou uma versão mais recente, o gesto de voltar preditivo será ativado por padrão.
Uso básico
Implemente NavigableListDetailPaneScaffold da seguinte maneira:
- Use uma classe que represente o conteúdo selecionado. Use uma classe
Parcelablepara salvar e restaurar o item de lista selecionado. Use o plug-in kotlin-parcelize para gerar o código para você. - Crie um
ThreePaneScaffoldNavigatorcomrememberListDetailPaneScaffoldNavigator.
Esse navegador é usado para alternar entre os painéis de lista, detalhes e extra. Ao
declarar um tipo genérico, o navegador também rastreia o estado do scaffold,
ou seja, qual MyItem está sendo exibido. Como esse tipo é parcelável, o
estado pode ser salvo e restaurado pelo navegador para processar automaticamente
as mudanças de configuração.
Transmita o navegador para o elemento combinável
NavigableListDetailPaneScaffold.Forneça a implementação do painel de lista para o
NavigableListDetailPaneScaffold. UseAnimatedPanepara aplicar as animações de painel padrão durante a navegação. Em seguida, useThreePaneScaffoldNavigatorpara navegar até o painel de detalhes,ListDetailPaneScaffoldRole.Detail, e mostrar o item transmitido.Inclua a implementação do painel de detalhes em
NavigableListDetailPaneScaffold.
Quando a navegação é concluída, currentDestination contém o painel para o qual o app
navegou, incluindo o conteúdo exibido no painel. A propriedade contentKey
é do mesmo tipo especificado na chamada original para que você possa acessar
todos os dados que precisa mostrar.
- Se quiser, mude o
defaultBackBehavioremNavigableListDetailPaneScaffold. Por padrão,NavigableListDetailPaneScaffoldusaPopUntilScaffoldValueChangeparadefaultBackBehavior.
Se o app exigir um padrão de navegação de retorno diferente, você poderá modificar esse
comportamento especificando outra opção de BackNavigationBehavior.
Opções de BackNavigationBehavior
A seção a seguir usa o exemplo de um app de e-mails com uma lista de e-mails em um painel e uma visualização detalhada no outro.
PopUntilScaffoldValueChange (padrão e recomendado na maioria dos casos)
Esse comportamento se concentra em mudanças na estrutura geral do layout. Em uma configuração de vários painéis, mudar o conteúdo do e-mail no painel de detalhes não altera a estrutura de layout. Portanto, o botão "Voltar" pode sair do app ou do gráfico de navegação atual, porque não há mudança de layout para reverter no contexto atual. Em um layout de painel único, pressionar "Voltar" vai pular as mudanças de conteúdo na visualização de detalhes e retornar à visualização em lista, já que isso representa uma mudança clara de layout.
Veja estes exemplos:
- Vários painéis:você está lendo um e-mail (Item 1) no painel de detalhes. Clicar em outro e-mail (Item 2) atualiza o painel de detalhes, mas os painéis de lista e de detalhes permanecem visíveis. Pressionar "Voltar" pode sair do app ou do fluxo de navegação atual.
- Painel único:você visualiza o Item 1 e, em seguida, o Item 2. Ao pressionar "Voltar", você retorna diretamente ao painel da lista de e-mails.
Use essa opção quando quiser que os usuários percebam transições de layout distintas a cada ação de voltar.
PopUntilContentChange
Esse comportamento prioriza o conteúdo exibido. Se você visualizar o Item 1 e depois o Item 2, pressionar "Voltar" vai retornar ao Item 1, independente do layout.
Veja estes exemplos:
- Vários painéis:você vê o Item 1 no painel de detalhes e clica no Item 2 na lista. O painel de detalhes é atualizado. Se você pressionar "Voltar", o painel de detalhes vai voltar para o Item 1.
- Painel único:ocorre a mesma reversão de conteúdo.
Use essa opção quando o usuário quiser retornar ao conteúdo visualizado anteriormente com a ação de voltar.
PopUntilCurrentDestinationChange
Esse comportamento remove a backstack até que o destino de navegação atual mude. Isso se aplica igualmente a layouts de painel único e de vários painéis.
Veja estes exemplos:
Independentemente de você estar em um layout de painel único ou múltiplo, pressionar "Voltar" sempre vai mover o foco do elemento de navegação destacado para o destino anterior. No nosso app de e-mails, isso significa que a indicação visual do painel selecionado vai mudar.
Use essa opção quando for crucial para a experiência do usuário manter uma indicação visual clara da navegação atual.
PopLatest
Essa opção remove apenas o destino mais recente da backstack. Use essa opção para navegação de retorno sem pular estados intermediários.
Depois de implementar essas etapas, o código vai ficar parecido com este:
NavigableListDetailPaneScaffold( navigator = navigator, listPane = { AnimatedPane { ListContent( words = sampleWords, selectionState = navigator.currentDestination?.contentKey?.let { SelectionVisibilityState.ShowSelection(it) } ?: SelectionVisibilityState.NoSelection, onWordClick = { word -> scope.launch { navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, word) } }, animatedVisibilityScope = this@AnimatedPane, sharedTransitionScope = this@SharedTransitionLayout ) } }, detailPane = { AnimatedPane { DetailContent( definedWord = navigator.currentDestination?.contentKey, animatedVisibilityScope = this@AnimatedPane, sharedTransitionScope = this@SharedTransitionLayout, onClosePane = { scope.launch { navigator.navigateBack( backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange ) } } ) } }