A ordem de apresentação é a ordem em que os serviços de acessibilidade navegam pelos elementos da interface. Em um app do Compose, os elementos são organizados na ordem de leitura esperada, que geralmente é da esquerda para a direita e de cima para baixo. No entanto, há alguns cenários em que o Compose pode precisar de mais dicas para determinar a ordem de leitura correta.
isTraversalGroup e traversalIndex são propriedades semânticas que
permitem influenciar a ordem de apresentação dos serviços de acessibilidade em cenários
em que o algoritmo de classificação padrão do Compose não é suficiente. isTraversalGroup
identifica grupos semanticamente importantes que precisam de personalização, enquanto
traversalIndex ajusta a ordem de elementos individuais dentro desses grupos.
É possível usar isTraversalGroup sozinho para indicar que todos os elementos de um grupo
precisam ser selecionados juntos ou com traversalIndex para uma personalização mais detalhada.
Use isTraversalGroup e traversalIndex no seu
app para controlar a ordem de apresentação do leitor de tela.
Agrupar elementos para travessia
isTraversalGroup é uma propriedade booleana que define se um nó de semântica
é um grupo de travessia. Esse tipo de nó tem a função de servir como um limite ou borda na organização dos nós filhos.
Definir isTraversalGroup = true em um nó significa que todos os filhos desse nó
são visitados antes de passar para outros elementos. É possível definir isTraversalGroup em
nós que não podem ser focados por leitores de tela, como colunas, linhas ou caixas.
O exemplo a seguir usa isTraversalGroup. Ele emite quatro elementos do texto. Os
dois elementos à esquerda pertencem a um elemento CardBox, enquanto os dois elementos à direita
pertencem a outro elemento CardBox:
// CardBox() function takes in top and bottom sample text. @Composable fun CardBox( topSampleText: String, bottomSampleText: String, modifier: Modifier = Modifier ) { Box(modifier) { Column { Text(topSampleText) Text(bottomSampleText) } } } @Composable fun TraversalGroupDemo() { val topSampleText1 = "This sentence is in " val bottomSampleText1 = "the left column." val topSampleText2 = "This sentence is " val bottomSampleText2 = "on the right." Row { CardBox( topSampleText1, bottomSampleText1 ) CardBox( topSampleText2, bottomSampleText2 ) } }
O código produz uma saída semelhante a esta:
Como nenhuma semântica foi definida, o comportamento padrão do leitor de tela é percorrer os elementos da esquerda para a direita e de cima para baixo. Devido a esse padrão, o TalkBack lê os fragmentos da frase na ordem errada:
"Esta frase está na" → "Esta frase está" → "coluna da esquerda." → "on the right."
Para ordenar os fragmentos corretamente, modifique o snippet original para definir
isTraversalGroup como true:
@Composable fun TraversalGroupDemo2() { val topSampleText1 = "This sentence is in " val bottomSampleText1 = "the left column." val topSampleText2 = "This sentence is" val bottomSampleText2 = "on the right." Row { CardBox( // 1, topSampleText1, bottomSampleText1, Modifier.semantics { isTraversalGroup = true } ) CardBox( // 2, topSampleText2, bottomSampleText2, Modifier.semantics { isTraversalGroup = true } ) } }
Como isTraversalGroup é definido especificamente em cada CardBox, os limites de CardBox
se aplicam ao classificar os elementos. Nesse caso, o CardBox
da esquerda é lido primeiro, seguido pelo CardBox da direita.
Agora, o TalkBack lê os fragmentos da frase na ordem correta:
"Esta frase está na" → "coluna da esquerda." → "Esta frase está" → "à direita."
Personalizar a ordem de apresentação
traversalIndex é uma propriedade flutuante que permite personalizar a ordem de apresentação do TalkBack. Se o agrupamento de elementos não for suficiente para o TalkBack
funcionar corretamente, use traversalIndex em conjunto com
isTraversalGroup para personalizar ainda mais a ordenação do leitor de tela.
A propriedade traversalIndex tem as seguintes características:
- Os elementos com valores de
traversalIndexmais baixos são priorizados primeiro. - Pode ser positivo ou negativo.
- O valor padrão é
0f. - Para que o índice de travessia influencie o comportamento de travessia, ele precisa ser
definido em um componente que possa ser selecionado e focado por serviços de
acessibilidade, como elementos na tela, como texto ou botões.
- Definir apenas
traversalIndexem, por exemplo, umColumnnão teria efeito, a menos que a coluna também tenhaisTraversalGroupdefinido.
- Definir apenas
O exemplo a seguir mostra como usar traversalIndex e
isTraversalGroup juntos.
Um mostrador do relógio é um cenário comum em que a ordem de apresentação padrão não funciona. O exemplo nesta seção é um seletor de horário, em que o usuário pode percorrer os números em um mostrador do relógio e selecionar dígitos para os espaços de hora e minuto.
No snippet simplificado a seguir, há um CircularLayout em que 12
números são desenhados, começando com 12 e se movendo no sentido horário ao redor do círculo:
@Composable fun ClockFaceDemo() { CircularLayout { repeat(12) { hour -> ClockText(hour) } } } @Composable private fun ClockText(value: Int) { Box(modifier = Modifier) { Text((if (value == 0) 12 else value).toString()) } }
Como o mostrador do relógio não é lido de forma lógica com a ordenação padrão da esquerda para a direita e de cima para baixo, o TalkBack lê os números fora de ordem. Para corrigir isso, use o valor do contador de incremento, conforme mostrado no snippet a seguir:
@Composable fun ClockFaceDemo() { CircularLayout(Modifier.semantics { isTraversalGroup = true }) { repeat(12) { hour -> ClockText(hour) } } } @Composable private fun ClockText(value: Int) { Box(modifier = Modifier.semantics { this.traversalIndex = value.toFloat() }) { Text((if (value == 0) 12 else value).toString()) } }
Para definir corretamente a ordem de apresentação, primeiro transforme o CircularLayout em um
grupo de apresentação e defina isTraversalGroup = true. Em seguida, conforme cada texto do relógio é
desenhado no layout, defina o traversalIndex correspondente como o valor
do contador.
Como o valor do contador aumenta continuamente, o traversalIndex de cada valor do relógio
é maior à medida que os números são adicionados à tela. O valor do relógio 0
tem um traversalIndex de 0, e o valor do relógio 1 tem um traversalIndex de 1.
Dessa forma, a ordem em que o TalkBack lê os elementos é definida. Agora, os números
dentro de CircularLayout são lidos na ordem esperada.
Como os traversalIndexes definidos são relativos apenas a outros
índices no mesmo agrupamento, o restante da ordem da tela foi
preservado. Em outras palavras, as mudanças semânticas mostradas no snippet de código
anterior modificam apenas a ordem no mostrador do relógio que tem
isTraversalGroup = true definido.
Sem definir a semântica de CircularLayout's como isTraversalGroup =
true, as mudanças de traversalIndex ainda se aplicam. No entanto, sem o
CircularLayout para vinculá-los, os doze dígitos do mostrador do relógio são lidos
por último, depois que todos os outros elementos na tela são visitados. Isso ocorre
porque todos os outros elementos têm um traversalIndex padrão de 0f, e os
elementos de texto do relógio são lidos depois de todos os outros elementos 0f.
Considerações sobre APIs
Considere o seguinte ao usar as APIs de travessia:
isTraversalGroup = trueprecisa ser definido no elemento pai que contém os elementos agrupados.traversalIndexprecisa ser definido em um componente filho que contenha semântica e seja selecionado por serviços de acessibilidade.- Verifique se todos os elementos que você está investigando estão no mesmo nível de
zIndex, já que isso também afeta a semântica e a ordem de apresentação. - Verifique se nenhuma semântica foi mesclada desnecessariamente, porque isso pode afetar os componentes em que os índices de travessia são aplicados.
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Acessibilidade no Compose
- [Material Design 2 no Compose][19]
- Como testar o layout do Compose