A ordem de apresentação é a ordem em que os serviços de acessibilidade navegam pelos elementos da interface. Em um app 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 casos em que o Compose pode precisar de dicas adicionais para determinar a ordem correta de leitura.
isTraversalGroup e traversalIndex são propriedades semânticas que
permitem influenciar a ordem de travessia para 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 nesses grupos.
É possível usar isTraversalGroup sozinho para indicar que todos os elementos de um grupo
precisam ser selecionados juntos ou com traversalIndex para mais personalização.
Use isTraversalGroup e traversalIndex no
app para controlar a ordem de passagem do leitor de tela.
Agrupar elementos para a 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 limite ou borda na organização dos filhos do nó.
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 com foco que não são leitores de tela, como colunas, linhas ou caixas.
O exemplo a seguir usa isTraversalGroup. Ele emite quatro elementos de 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. Por causa desse padrão, o TalkBack lê os fragmentos da frase na ordem errada:
"Esta frase está em" → "Esta frase está" → "na coluna esquerda." → "à direita".
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
são aplicados ao classificar os elementos. Nesse caso, o CardBox
esquerdo é lido primeiro, seguido pelo CardBox direito.
Agora, o TalkBack lê os fragmentos da frase na ordem correta:
"Esta frase está na" → "coluna esquerda." → "Esta frase está" → "na direita."
Personalizar a ordem de apresentação
traversalIndex é uma propriedade float que permite personalizar a ordem de
navegação do TalkBack. Se agrupar elementos não for suficiente para que o TalkBack
funcione corretamente, use traversalIndex em conjunto com
isTraversalGroup para personalizar ainda mais a ordem 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 translação influencie o comportamento de translação, ele precisa ser
definido em um componente que será selecionável e focalizável por serviços de
acessibilidade, como elementos na tela, como texto ou botões.
- Definir apenas
traversalIndexem, por exemplo, umColumnnão teria nenhum efeito, a menos que a coluna também tenhaisTraversalGroupdefinido.
- Definir apenas
O exemplo a seguir mostra como usar traversalIndex e
isTraversalGroup juntos.
Um mostrador de relógio é um cenário comum em que a ordenação de travessia padrão não funciona. O exemplo desta 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 intervalos de hora e minuto.
No snippet simplificado a seguir, há uma 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 de relógio não é lido de forma lógica com a ordem 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 de incremento do contador, 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 travessia, primeiro torne o CircularLayout um
grupo de travessia 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 os lê é definida. Agora, os números
dentro do CircularLayout são lidos na ordem esperada.
Como os traversalIndexes definidos são relativos a outros
índices no mesmo grupo, 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 dentro do mostrador do relógio que tem
isTraversalGroup = true definido.
Sem a definição da semântica CircularLayout's como isTraversalGroup =
true, as mudanças 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 pai que contém os elementos agrupados.traversalIndexprecisa ser definido em um componente filho que contém semântica e será selecionado pelos serviços de acessibilidade.- Verifique se todos os elementos que você está investigando estão no mesmo
nível de
zIndex, porque isso também afeta a semântica e a ordem de travessia. - Verifique se nenhuma semântica é mesclada desnecessariamente, já que 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