Os detalhes e listas são um padrão da interface que consiste em um layout de painel duplo, em que um painel apresenta uma lista de itens e 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. Os detalhes e listas também podem ser usados para caminhos menos essenciais, como dividir as preferências do app em uma lista de categorias com as preferências de cada uma no painel de detalhes.
Implementar o padrão da interface com ListDetailPaneScaffold
O ListDetailPaneScaffold
é um elemento combinável que simplifica a implementação do
padrão de detalhes e listas no app. Um scaffolding de detalhes e listas pode consistir em até
três painéis: um de lista, um de detalhes e outro opcional. O
scaffold processa cálculos do espaço da tela. Quando um tamanho de tela suficiente estiver
disponível, o painel de detalhes vai ser exibido ao lado do painel de lista. Em tamanhos
de tela pequenos, o scaffold muda automaticamente para mostrar a
lista ou o painel de detalhes em tela cheia.
Declarar dependências
O ListDetailPaneScaffold
faz parte da biblioteca adaptável do Material 3.
Adicione uma dependência para a biblioteca no arquivo build.gradle
do seu app
ou módulo:
implementation("androidx.compose.material3.adaptive:adaptive:1.0.0-alpha07")
implementation("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha07")
implementation("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha07")
Uso básico
Confira a seguir o uso básico do ListDetailPaneScaffold
:
Armazene o item selecionado na lista no momento em uma variável de estado mutável. A variável contém o item que será exibido no painel de detalhes. Normalmente, inicialize o item selecionado no momento com
null
, indicando que nenhuma seleção foi feita ainda.class MyItem(val id: Int) { companion object { val Saver: Saver<MyItem?, Int> = Saver( { it?.id }, ::MyItem, ) } }
var selectedItem: MyItem? by rememberSaveable(stateSaver = MyItem.Saver) { mutableStateOf(null) }
Crie o
ThreePaneScaffoldNavigator
comrememberListDetailPaneScaffoldNavigator
e adicione umBackHandler
. Esse navegador é usado para alternar entre a lista, os detalhes e os painéis extras, além de fornecer o estado ao scaffold. OBackHandler
adicionado oferece suporte para navegar de volta usando o gesto ou botão "Voltar" do sistema. O comportamento esperado do botão "Voltar" para umaListDetailPaneScaffold
depende do tamanho da janela e do valor do scaffold atual. Se oListDetailPaneScaffold
for compatível com a volta ao estado atual,canNavigateBack()
serátrue
, ativando oBackHandler
.val navigator = rememberListDetailPaneScaffoldNavigator<Nothing>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() }
Transmita o
scaffoldState
donavigator
que você criou para o elemento combinávelListDetailPaneScaffold
.ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, // ... )
Forneça a implementação do painel de lista ao
ListDetailPaneScaffold
. Confira se a implementação inclui um argumento de callback para capturar o item recém-selecionado. Quando esse callback for acionado, atualize a variável de estadoselectedItem
e useThreePaneScaffoldNavigator
para exibir o painel de detalhes (ListDetailPaneScaffoldRole.Detail
).ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane(Modifier) { MyList( onItemClick = { id -> // Set current item selectedItem = id // Switch focus to detail pane navigator.navigateTo(ListDetailPaneScaffoldRole.Detail) } ) } }, // ... )
Inclua a implementação do painel de detalhes no
ListDetailPaneScaffold
. Mostre o conteúdo detalhado somente seselectedItem
não for nulo.ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = // ... detailPane = { AnimatedPane(Modifier) { selectedItem?.let { item -> MyDetails(item) } } }, )
Depois de implementar as etapas acima, o código vai ficar parecido com este:
// Currently selected item var selectedItem: MyItem? by rememberSaveable(stateSaver = MyItem.Saver) { mutableStateOf(null) } // Create the ListDetailPaneScaffoldState val navigator = rememberListDetailPaneScaffoldNavigator<Nothing>() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() } ListDetailPaneScaffold( directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { AnimatedPane(Modifier) { MyList( onItemClick = { id -> // Set current item selectedItem = id // Display the detail pane navigator.navigateTo(ListDetailPaneScaffoldRole.Detail) }, ) } }, detailPane = { AnimatedPane(Modifier) { // Show the detail pane content if selected item is available selectedItem?.let { item -> MyDetails(item) } } }, )