L'ordine di attraversamento è l'ordine in cui i servizi di accessibilità navigano tra gli elementi UI. In un'app Compose, gli elementi sono disposti nell'ordine di lettura previsto, che di solito è da sinistra a destra, poi dall'alto verso il basso. Tuttavia, esistono alcuni scenari in cui Compose potrebbe aver bisogno di ulteriori suggerimenti per determinare l'ordine di lettura corretto.
isTraversalGroup e traversalIndex sono proprietà semantiche che ti consentono di influenzare l'ordine di attraversamento per i servizi di accessibilità in scenari in cui l'algoritmo di ordinamento predefinito di Compose non è sufficiente. isTraversalGroup identifica i gruppi semanticamente importanti che richiedono la personalizzazione, mentre traversalIndex regola l'ordine dei singoli elementi all'interno di questi gruppi.
Puoi utilizzare isTraversalGroup da solo per indicare che tutti gli elementi di un gruppo devono essere selezionati insieme o con traversalIndex per un'ulteriore personalizzazione.
Utilizza isTraversalGroup e traversalIndex nella tua app per controllare l'ordine di attraversamento dello screen reader.
Raggruppa gli elementi per l'esplorazione
isTraversalGroup è una proprietà booleana che definisce se un nodo semantics è un gruppo di attraversamento. Questo tipo di nodo ha la funzione di fungere da confine o bordo nell'organizzazione dei nodi secondari.
L'impostazione di isTraversalGroup = true su un nodo indica che tutti i nodi secondari di quel nodo vengono visitati prima di passare ad altri elementi. Puoi impostare isTraversalGroup su
nodi attivabili non screen reader, come colonne, righe o caselle.
L'esempio seguente utilizza isTraversalGroup. Genera quattro elementi di testo. I due elementi a sinistra appartengono a un elemento CardBox, mentre i due elementi a destra appartengono a un altro 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 ) } }
Il codice produce un output simile al seguente:
Poiché non è stata impostata alcuna semantica, il comportamento predefinito dello screen reader è attraversare gli elementi da sinistra a destra e dall'alto verso il basso. A causa di questa impostazione predefinita, TalkBack legge i frammenti di frase nell'ordine sbagliato:
"This sentence is in" → "This sentence is" → "the left column." → "on the right."
Per ordinare correttamente i frammenti, modifica lo snippet originale per impostare isTraversalGroup su 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 } ) } }
Poiché isTraversalGroup è impostato in modo specifico su ogni CardBox, i limiti di CardBox si applicano quando si ordinano i relativi elementi. In questo caso, viene letto prima il CardBox a sinistra, seguito dal CardBox a destra.
Ora TalkBack legge i frammenti di frase nell'ordine corretto:
"This sentence is in" → "the left column." → "Questa frase è" → "a destra".
Personalizza l'ordine di attraversamento
traversalIndex è una proprietà float che ti consente di personalizzare l'ordine di attraversamento di TalkBack. Se il raggruppamento degli elementi non è sufficiente per il corretto funzionamento di TalkBack, utilizza traversalIndex insieme a isTraversalGroup per personalizzare ulteriormente l'ordine dello screen reader.
La proprietà traversalIndex ha le seguenti caratteristiche:
- Gli elementi con valori
traversalIndexpiù bassi hanno la priorità. - Può essere positivo o negativo.
- Il valore predefinito è
0f. - Affinché l'indice di attraversamento influisca sul comportamento di attraversamento, deve essere impostato su un componente che sarà selezionabile e attivabile dai servizi di accessibilità, ad esempio elementi sullo schermo come testo o pulsanti.
- L'impostazione di
traversalIndex, ad esempio, su unColumnnon avrebbe alcun effetto, a meno che la colonna non abbia ancheisTraversalGroupimpostato.
- L'impostazione di
L'esempio seguente mostra come utilizzare traversalIndex e
isTraversalGroup insieme.
Un quadrante orologio è uno scenario comune in cui l'ordine di attraversamento standard non funziona. L'esempio in questa sezione è un selettore dell'ora, in cui un utente può scorrere i numeri su un quadrante orologio e selezionare le cifre per gli slot di ore e minuti.
Nel seguente snippet semplificato, è presente un CircularLayout in cui vengono disegnati 12 numeri, a partire da 12 e spostandosi in senso orario lungo il cerchio:
@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()) } }
Poiché il quadrante dell'orologio non viene letto logicamente con l'ordine predefinito da sinistra a destra e dall'alto verso il basso, TalkBack legge i numeri in ordine sparso. Per correggere questo problema, utilizza il valore del contatore incrementale, come mostrato nello snippet seguente:
@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()) } }
Per impostare correttamente l'ordine di attraversamento, imposta prima CircularLayout come gruppo di attraversamento e imposta isTraversalGroup = true. Poi, man mano che ogni testo dell'orologio viene disegnato sul layout, imposta il relativo traversalIndex sul valore del contatore.
Poiché il valore del contatore aumenta continuamente, il valore traversalIndex di ogni valore di clock è maggiore man mano che i numeri vengono aggiunti allo schermo: il valore di clock 0 ha un traversalIndex pari a 0 e il valore di clock 1 ha un traversalIndex pari a 1.
In questo modo, viene impostato l'ordine in cui TalkBack li legge. Ora i numeri all'interno di CircularLayout vengono letti nell'ordine previsto.
Poiché i traversalIndexes impostati sono relativi solo ad altri indici all'interno dello stesso raggruppamento, il resto dell'ordine delle schermate è stato conservato. In altre parole, le modifiche semantiche mostrate nello snippet di codice precedente modificano solo l'ordine all'interno del quadrante orologio con isTraversalGroup = true impostato.
Tieni presente che, senza impostare la semantica CircularLayout's su isTraversalGroup =
true, le modifiche di traversalIndex vengono comunque applicate. Tuttavia, senza l'attributo CircularLayout per associarle, le dodici cifre del quadrante dell'orologio vengono lette per ultime, dopo che sono stati visitati tutti gli altri elementi sullo schermo. Questo accade perché tutti gli altri elementi hanno un valore traversalIndex predefinito di 0f e gli elementi di testo dell'orologio vengono letti dopo tutti gli altri elementi 0f.
Considerazioni sulle API
Quando utilizzi le API di attraversamento, tieni presente quanto segue:
isTraversalGroup = truedeve essere impostato sull'elemento principale contenente gli elementi raggruppati.traversalIndexdeve essere impostato su un componente secondario che contiene la semantica e verrà selezionato dai servizi di accessibilità.- Assicurati che tutti gli elementi che stai esaminando siano allo stesso livello
zIndex, poiché ciò influisce anche sulla semantica e sull'ordine di attraversamento. - Assicurati che non vengano unite semantiche non necessarie, in quanto ciò potrebbe influire sui componenti a cui vengono applicati gli indici di attraversamento.
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Accessibilità in Compose
- [Material Design 2 in Compose][19]
- Test del layout di Compose