Listas lentas em uma grade

Ícone de classificação de quatro estrelas

O elemento combinável Grid cria layouts de tela estruturais e bidimensionais. Grid define uma estrutura de layout responsivo usando faixas (linhas e colunas) e lacunas definidas explicitamente como a arquitetura fundamental da sua interface.

Como Grid é um contêiner estrutural em vez de um contêiner de carregamento lento, é necessário definir explicitamente todos os elementos colocados nele sem reciclar itens na rolagem. Como resultado, renderizar conjuntos de dados grandes ou dinâmicos diretamente em um Grid pode causar gargalos de desempenho, já que todos os itens são compostos simultaneamente.

Para mostrar grandes coleções de dados em um layout de tela estruturado, incorpore componentes lentos, como LazyColumn ou LazyRow nas células Grid. No entanto, as faixas flexíveis (com especificações como 1.fr) consultam os tamanhos intrínsecos dos elementos filhos. Como SubcomposeLayout não é compatível com transmissões de medição intrínseca, colocar uma lista lenta em uma faixa flexível causa uma falha de IllegalStateException. Para colocar listas lentas com segurança em uma faixa de grade flexível, use o dimensionamento GridTrackSize.MinMax (como minmax(0.dp, 1.fr)) para ignorar a transmissão de medição intrínseca.

Layout de tela com um cabeçalho na parte de cima, uma lista rolável de itens na área de conteúdo principal e um rodapé na parte de baixo.
Figura 1. Layout estrutural da tela com um cabeçalho, um rodapé e um LazyColumn incorporado para conteúdo.

Práticas recomendadas

  • Use listas lentas em vez de loops explícitos grandes: para mostrar conjuntos de dados grandes ou dinâmicos em um Grid estruturado, incorpore componentes lentos (normalmente LazyColumn ou LazyRow) em células de grade específicas em vez de criar loops explícitos grandes em itens, já que o Grid não recicla itens e tem um limite de 1.000 faixas.
  • Use o dimensionamento de rastreamento MinMax para listas lentas: como LazyColumn e LazyRow não oferecem suporte a transmissões de medição intrínseca (consulte SubcomposeLayout), use GridTrackSize.MinMax em faixas flexíveis que hospedam componentes lentos para ignorar medições intrínsecas com segurança.

Ingredientes

  • Grid: layout combinável que coloca itens em uma estrutura de grade bidimensional configurada usando faixas de linha e coluna explícitas.
  • LazyColumn: lista de rolagem vertical que compõe e recicla apenas os itens visíveis na tela no momento.
  • GridTrackSize.MinMax: propriedade de dimensionamento de rastreamento que define limites flexíveis (min e max) para hospedar componentes lentos com segurança sem acionar falhas de medição de tempo de execução.
  • gridItem: extensão Modifier do Compose que atribui um elemento de interface filho a uma célula específica ou área nomeada dentro de um Grid.

Etapas

Estruture o layout da tela definindo identificadores de área semântica, configurando faixas de grade com dimensionamento minmax para compatibilidade com listas lentas e incorporando LazyColumn na área de conteúdo da grade.

1. Configurar faixas de grade e áreas nomeadas

Crie uma classe enum para representar as diferentes regiões do layout da tela e defina uma lambda GridConfigurationScope para as faixas de layout e áreas nomeadas. Use GridTrackSize.MaxContent para as linhas de cabeçalho e rodapé de acordo com as dimensões do conteúdo e minmax(0.dp, 1.fr) para a faixa de conteúdo que hospeda a lista de carregamento lento para alocar espaço flexível sem consultar medidas intrínsecas não compatíveis:

enum class ScreenArea {
    Header,
    Content,
    Footer
}


val lazyConfig: GridConfigurationScope.() -> Unit = {
    column(minmax(0.dp, 1.fr))
    row(GridTrackSize.MaxContent)
    row(minmax(0.dp, 1.fr))
    row(GridTrackSize.MaxContent)

    area(ScreenArea.Header, row = 1, column = 1)
    area(ScreenArea.Content, row = 2, column = 1)
    area(ScreenArea.Footer, row = 3, column = 1)
    gap(8.dp)
}

2. Colocar componentes estáticos na grade

No elemento combinável, transmita lazyConfig para o contêiner Grid. Na lambda content, coloque componentes estáticos (Header e Footer) e posicione-os usando Modifier.gridItem() com os respectivos identificadores de área.

3. Incorporar LazyColumn na área de conteúdo

Na célula de conteúdo, incorpore LazyColumn usando Modifier.gridItem(ScreenArea.Content). Como a faixa de conteúdo foi configurada com minmax(0.dp, 1.fr) na etapa 1, LazyColumn pode medir e reciclar itens com segurança na rolagem sem consultar dimensões intrínsecas não compatíveis:

@Composable
fun GridWithLazyColumn(
    modifier: Modifier = Modifier,
    items: List<String> = emptyList(),
) {
    Grid(
        modifier = modifier.fillMaxSize(),
        config = lazyConfig
    ) {
        Text("Header", Modifier.gridItem(ScreenArea.Header).padding(16.dp))
        Text("Footer", Modifier.gridItem(ScreenArea.Footer).padding(16.dp))

        // LazyColumn placed in the content area for large datasets
        LazyColumn(
            modifier = Modifier
                .gridItem(ScreenArea.Content)
                .fillMaxSize(),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            items(items) { item ->
                Text(item, Modifier.padding(16.dp))
            }
        }
    }
}

Resultados

O layout da tela agora usa a API Grid para definir a estrutura geral da página bidimensional, incorporando um LazyColumn em uma faixa flexível com dimensionamento minmax para reciclar itens da lista de maneira eficiente e evitar exceções de tempo de execução.

Outros recursos