Criar um layout de detalhes e listas

Detalhes e listas são um padrão de interface que consiste em um layout de painel duplo em que um painel apresenta uma lista de itens e outro painel exibe os detalhes dos itens selecionados da lista.

O padrão é particularmente útil para aplicativos que oferecem informações sobre elementos de grandes coleções, por exemplo, um cliente de e-mail com 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 críticos, como dividir o app preferências em uma lista de categorias, com as preferências de cada categoria em no painel de detalhes.

Implementar o padrão da interface com ListDetailPaneScaffold

ListDetailPaneScaffold é um elemento combinável que simplifica a implementação de o padrão de detalhes e listas no app. Um scaffolding de detalhes e listas pode consistir em até três painéis: um painel de lista, um painel de detalhes e um painel extra opcional. A scaffold lida com cálculos de espaço de tela. Quando o tamanho de tela suficiente for disponível, o painel de detalhes é exibido ao lado do painel de lista. Em uma tela pequena tamanhos, o scaffold muda automaticamente para a exibição da lista ou em tela cheia com o painel de detalhes.

Um painel de detalhes ao lado da página da lista.
Figura 1. Quando há tamanho de tela suficiente disponível, os detalhes ao lado do painel de lista.
Depois que um item é selecionado, o painel de detalhes cobre a tela inteira.
Figura 2. Quando o tamanho da tela é limitado, o painel de detalhes (já que um item foi selecionado) ocupa todo o espaço.

Declarar dependências

ListDetailPaneScaffold faz parte do layout adaptável do Material 3. biblioteca.

Adicione as três dependências relacionadas a seguir ao arquivo build.gradle da sua 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'

  • adaptativo: elementos básicos de baixo nível, como HingeInfo e Posture
  • adaptive-layout: layouts adaptáveis como ListDetailPaneScaffold e SupportingPaneScaffold
  • adaptive-navigation: elementos combináveis para navegar dentro e entre os painéis
.

Uso básico

Implemente ListDetailPaneScaffold desta maneira:

  1. Use uma classe que represente o conteúdo a ser selecionado. Esta turma precisa ser Parcelable para oferecer suporte ao salvamento e restaurando o item selecionado. Usar a classe kotlin-parcelize plug-in para gerar o código.

    @Parcelize
    class MyItem(val id: Int) : Parcelable

  2. Crie uma ThreePaneScaffoldNavigator com rememberListDetailPaneScaffoldNavigator e adicionar um BackHandler. Isso Navigator é usado para mover entre a lista, os detalhes e os painéis extras. De declarando um tipo genérico, o navegador também rastreia o estado da scaffold, ou seja, qual MyItem está sendo exibido. Como esse tipo é parcelable, o estado pode ser salvo e restaurado pelo navegador para processam automaticamente as mudanças de configuração. A BackHandler é compatível com a navegação de volta usando o gesto "Voltar" do sistema; ou . O comportamento esperado do botão "Voltar" em um ListDetailPaneScaffold depende do tamanho da janela e do scaffolding atual. . Se o ListDetailPaneScaffold oferecer suporte à reversão com o estado atual, canNavigateBack() será true, ativando a BackHandler.

    val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
    
    BackHandler(navigator.canNavigateBack()) {
        navigator.navigateBack()
    }

  3. Transmita o scaffoldState do navigator para o ListDetailPaneScaffold combinável.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        // ...
    )

  4. Forneça a implementação do painel de lista ao ListDetailPaneScaffold. Usar AnimatedPane para aplicar as animações de painel padrão durante a navegação. Em seguida, use ThreePaneScaffoldNavigator para acessar o painel de detalhes. ListDetailPaneScaffoldRole.Detail e exibe o item transmitido.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        listPane = {
            AnimatedPane {
                MyList(
                    onItemClick = { item ->
                        // Navigate to the detail pane with the passed item
                        navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
                    }
                )
            }
        },
        // ...
    )

  5. Inclua a implementação do painel de detalhes em ListDetailPaneScaffold. Quando a navegação for concluída, o arquivo currentDestination vai conter o painel que pelo app, incluindo o conteúdo exibido no painel. A A propriedade content é do mesmo tipo especificado na chamada de remember original. (MyItem neste exemplo), de modo que você também pode acessar a propriedade para quaisquer dados que você precisa exibir.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        listPane =
        // ...
        detailPane = {
            AnimatedPane {
                navigator.currentDestination?.content?.let {
                    MyDetails(it)
                }
            }
        },
    )

Depois de implementar as etapas acima, o código vai ficar parecido com este:

val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

ListDetailPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    listPane = {
        AnimatedPane {
            MyList(
                onItemClick = { item ->
                    // Navigate to the detail pane with the passed item
                    navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
                },
            )
        }
    },
    detailPane = {
        AnimatedPane {
            // Show the detail pane content if selected item is available
            navigator.currentDestination?.content?.let {
                MyDetails(it)
            }
        }
    },
)