AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79016499
Accepted
BobDoolittle
BobDoolittle
Asked: 2024-09-24 06:58:59 +0800 CST2024-09-24 06:58:59 +0800 CST 2024-09-24 06:58:59 +0800 CST

Compondo um Jetpack LazyGrid de FilterChip

  • 772

Estou tentando criar uma UI que se parece muito com a que está no topo da página do Material3 Chip . insira a descrição da imagem aqui Parece que a melhor maneira de fazer isso é construir um LazyVerticalStaggeredGrid, cujo conteúdo consiste em FilteredChipcomposables.

Um único FilteredChip em uma coluna é exibido perfeitamente. Mas quando eu o envolvo em um LazyVerticalStaggeredGrid, ele ignora as restrições de tamanho do texto e reduz a largura de cada chip, e fornece uma altura muito grande. De acordo com o Layout Inspector, o texto tem largura de 0 dp e altura de 140 dp. Além disso, ele ignora meu esquema de cores de tema.

Eu esperava que ele medisse o tamanho do texto dentro do Text composable e passasse isso para determinar a largura de cada chip e a altura de cada linha. Se não é assim que LazyGrids funcionam, como devo abordar isso?

Aqui está um exemplo muito simples que ilustra meu problema:

@Composable
fun VerticalGrid(
    contentList: List<String>,
    modifier: Modifier = Modifier,
) {
    LazyVerticalStaggeredGrid(
        horizontalArrangement = Arrangement.spacedBy(16.dp),
        columns = StaggeredGridCells.Adaptive(minSize = 4.dp),
        verticalItemSpacing = 8.dp,
        modifier = modifier.fillMaxSize()
    ) {
        var selected = false
        items(contentList) { text ->
            Chip(text, selected, { selected = !selected }, modifier)
        }
    }
}

@Composable
fun Chip(
    text: String,
    selected: Boolean,
    onClick: () -> (Unit),
    modifier: Modifier = Modifier,
) {
    FilterChip(
        onClick = onClick,
        label = { Text(text = text) },
        selected = selected,
        modifier = modifier
    )
}

object Content {
    val contentList = mutableListOf<String>()

    init {
        for (i in 10..50) {
            contentList.add("Label$i")
        }
    }
}

@Preview(showBackground = true)
@Composable
fun ChipPreview1() {
    StaggeredGridOfChipsTheme {
        Column(
            verticalArrangement = Arrangement.Top,
            modifier = Modifier.fillMaxSize()
        ) {
            Chip("Hello", true, {})
        }
    }
}

@Preview(showBackground = true)
@Composable
fun VerticalGridPreview1() {
    StaggeredGridOfChipsTheme {
        VerticalGrid(Content.contentList, Modifier.fillMaxSize())
    }
}

Isso resulta no seguinte comportamento: insira a descrição da imagem aqui

Qualquer dica que pudesse me ajudar a solucionar esse problema também seria bem-vinda.

kotlin
  • 1 1 respostas
  • 31 Views

1 respostas

  • Voted
  1. Best Answer
    Leviathan
    2024-09-24T07:39:18+08:002024-09-24T07:39:18+08:00

    Você restringe o tamanho de cada coluna no LazyVerticalStaggeredGridusando StaggeredGridCells.Adaptive(minSize = 4.dp). Da documentação:

    Define uma grade com o máximo de linhas ou colunas possível, desde que cada célula tenha pelo menos minSizeespaço e todo o espaço extra seja distribuído uniformemente.

    Isso significa que as colunas são apenas 4.dplargas (+ algum espaço marginal extra). Tente defini-lo para 80.dppara ver a diferença.

    Se seus chips não forem todos do mesmo tamanho, uma grade não é a melhor escolha, você deve usar uma FlowRow:

    FlowRow(
        modifier = modifier,
        horizontalArrangement = Arrangement.SpaceBetween,
    ) {
        contentList.forEach { text ->
            var selected by remember { mutableStateOf(false) }
            Chip(text, selected, { selected = !selected })
        }
    }
    

    Vamos dar uma olhada mais de perto no que LazyVerticalStaggeredGridrealmente é:

    1. LazyVertical StaggeredGrid: O comportamento vertical preguiçoso é comparável ao de um LazyColumn. Isso significa que você não tem limitação vertical, você pode rolar infinitamente (desde que haja elementos disponíveis para exibir, é claro).

    2. LazyVerticalStaggered Grid : Uma grade consiste em linhas e colunas onde todas as células têm o mesmo tamanho. Elas não precisam ser quadradas (ou seja, largura==altura), mas cada célula tem a mesma largura que todas as outras células. O mesmo se aplica à altura. Um rgid é como um raster.

    3. LazyVertical Staggered Grid: Uma grade escalonada , por outro lado, pode ter células de tamanho variável. Obviamente, as células não podem ter um tamanho arbitrário, caso contrário, haveria muito espaço vazio e não utilizado. O escalonamento se relaciona ao tamanho variável na direção de rolagem , somente isso é variável. Em uma grade escalonada de rolagem vertical, essa é a altura .

    Veja este exemplo dos documentos :

    LazyVerticalStaggeredGrid com três colunas fixas

    Ele tem três colunas de largura igual que podem ser roladas verticalmente. Cada célula tem a mesma largura, mas uma altura variável . É assim que um LazyVerticalStaggeredGridnormalmente se parece.

    Essa imagem é do segundo exemplo do link acima. Ela define explicitamente o número de colunas para três usando StaggeredGridCells.Fixed(3). A largura real das colunas depende da largura geral disponível, cada coluna recebe um terço dela. Quando o dispositivo é girado para o modo paisagem, ainda serão três colunas, cada uma com uma largura muito maior.

    O primeiro exemplo , no entanto, usa StaggeredGridCells.Adaptive(200.dp), semelhante ao que você usou no seu código. Isso significa que o número de colunas é flexível e se ajusta ao espaço disponível. A única restrição é que cada coluna deve ter pelo menos 200.dp largura. Então, vamos supor que a largura geral disponível para o LazyVerticalStaggeredGrid seja 500.dp. Isso significa que apenas duas colunas com pelo menos 200.dppodem caber. As restantes 100.dpsão distribuídas uniformemente para as outras colunas, então cada uma é 250.dplarga. Quando o dispositivo é girado para o modo paisagem e agora há 1000.dpdisponível, então você teria cinco colunas, cada uma exatamente 200.dplarga. É por isso que é chamado de Adaptive: O número de colunas se adapta ao espaço disponível.

    Agora, quando o conteúdo real de cada célula é exibido (imagens nesses exemplos, Chips no seu código), o conteúdo é redimensionado para caber. É assim que os componentes de layout do Compose funcionam em geral, não é específico para LazyVerticalStaggeredGrid. No seu código, as colunas são apenas 4.dplargas (mais uma fração insignificante do espaço restante), então os Chips são solicitados a se redimensionarem de acordo. Eles fazem o melhor que podem, envolvendo cada letra em uma nova linha para que a largura fique a menor possível enquanto cresce em altura. Isso é possível porque a altura não é restrita (veja o ponto 3 acima, a grade é verticalmente escalonada .)


    Não relacionado, mas ainda assim digno de nota:

    1. Você deve passar o modifierparâmetro de VerticalGridsomente para o primeiro elemento ( LazyVerticalStaggeredGrid), não para outros elementos (o Chips). Caso contrário, ele bagunçará a semântica do modificador e se tornará imprevisível para o chamador.

    2. Em VerticalGridvocê declara a variável selectedcomo um Boolean simples. Precisa ser um MutableState<Boolean>though se você quiser que seus Chips sejam atualizados adequadamente. Além disso, essa variável precisa ser movida dentro do itemsloop para que cada chip tenha seu próprio State, caso contrário, alternar um chip alternará todos os outros também. Compare com como eu fiz acima no exemplo FlowRow.

    3. Você pode criar seus dados de teste Content.contentListmuito mais facilmente. Se quiser uma lista de 41 rótulos diferentes, você pode simplesmente usar isto:

      List(41) { "Label$it" }
      

      Se você quiser que seja de 10 a 50 inclusive, você pode usar isto:

      List(41) { "Label${it + 10}" }
      
    • 2

relate perguntas

  • Ao usar ?.get para acessar o parâmetro Kotlin gera um erro Referência não resolvida

  • Kotlin - Como processar dados em paralelo corretamente?

  • como combinar anotação e estilo no Compose?

  • Kotlin coleta SharedFlow não está coletando

  • Como usar o filtro de vários termos no Spring Data Elasticsearch?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve