L'ordine di attraversamento è l'ordine in cui i servizi di accessibilità esplorano gli elementi dell'interfaccia utente. In un'app Scrivi, gli elementi sono disposti nell'ordine di lettura previsto, solitamente da sinistra verso destra e dall'alto verso il basso. Tuttavia, in alcuni scenari, Scrivi potrebbe richiedere suggerimenti aggiuntivi per determinare l'ordine di lettura corretto.
isTraversalGroup
e traversalIndex
sono proprietà semantiche che 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 oppure con traversalIndex
per ulteriori personalizzazioni.
Utilizza isTraversalGroup
e traversalIndex
nella
app per controllare l'ordine di esplorazione dello screen reader.
Raggruppare gli elementi per la navigazione
isTraversalGroup
è una proprietà booleana che definisce se un nodo semantico è un gruppo di esplorazione. Questo tipo di nodo ha la funzione di delimitare o bordare l'organizzazione dei nodi secondari.
L'impostazione 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 non attivabili tramite lo screen reader, ad esempio colonne, righe o caselle.
L'esempio seguente utilizza isTraversalGroup
. Emette 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 è esaminare 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:
"Questa frase si trova nella" → "Questa frase si trova nella" → "colonna a sinistra". → "a destra."
Per ordinare correttamente i frammenti, modifica lo snippet originale impostandoisTraversalGroup
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 specificamente su ogni CardBox
, i limiti di CardBox
vengono applicati durante l'ordinamento dei 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:
"Questa frase si trova nella" → "colonna di sinistra". → "Questa frase è" → "a destra."
Personalizzare l'ordine di attraversamento
traversalIndex
è una proprietà float che consente di personalizzare l'ordine di esplorazione di TalkBack. Se raggruppare gli 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
traversalIndex
più bassi hanno una priorità maggiore. - 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 acquisibile dai servizi di accessibilità, ad esempio elementi sullo schermo come testo o pulsanti.
- L'impostazione di solo
traversalIndex
, ad esempio, su unColumn
non avrebbe alcun effetto, a meno che nella colonna non sia impostato ancheisTraversalGroup
.
- L'impostazione di solo
L'esempio seguente mostra come utilizzare traversalIndex
e
isTraversalGroup
insieme.
Un quadrante è uno scenario comune in cui l'ordinamento 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 e selezionare le cifre per le ore e i minuti.

Nel seguente snippet semplificato è presente un CircularLayout
in cui sono disegnati 12
numeri, a partire da 12 e procedendo in senso orario attorno al 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 non viene letto in modo logico con l'ordinamento predefinito da sinistra a destra e dall'alto verso il basso, TalkBack legge i numeri fuori sequenza. Per risolvere il problema, utilizza il valore del contatore in aumento, 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, crea innanzitutto CircularLayout
come gruppo di attraversamento e imposta isTraversalGroup = true
. Poi, man mano che ogni testo dell'orologio viene visualizzato nel layout, imposta il relativo traversalIndex
sul valore del contatore.
Poiché il valore del contatore aumenta continuamente, il valore traversalIndex
di ogni valore dell'orologio è maggiore man mano che i numeri vengono aggiunti allo schermo: il valore dell'orologio 0 ha un valore traversalIndex
pari a 0 e il valore dell'orologio 1 ha un valore traversalIndex
pari a 1.
In questo modo, viene impostato l'ordine in cui TalkBack le legge. Ora i numeri all'interno di CircularLayout
vengono letti nell'ordine previsto.
Poiché i valori traversalIndexes
impostati si riferiscono solo ad altri indici all'interno dello stesso raggruppamento, il resto dell'ordine dello schermo è stato mantenuto. In altre parole, le modifiche semantiche mostrate nello snippet di codice precedente modificano solo l'ordine all'interno del quadrante con isTraversalGroup = true
impostato.
Tieni presente che, senza impostare la semantica CircularLayout's
su isTraversalGroup =
true
, le modifiche traversalIndex
vengono comunque applicate. Tuttavia, senza il carattere CircularLayout
per legarli, le dodici cifre del quadrante 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 relative alle API
Tieni presente quanto segue quando utilizzi le API di attraversamento:
isTraversalGroup = true
deve essere impostato sull'elemento principale contenente gli elementi raggruppati.traversalIndex
deve 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
, in quanto 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 Componi
- [Material Design 2 in Compose][19]
- Testare il layout di Componi