Par défaut, le comportement du lecteur d'écran d'accessibilité dans une application Compose est implémenté dans l'ordre de lecture attendu, généralement de gauche à droite, puis de haut en bas.
Toutefois, dans certains types de mises en page d'application, l'algorithme ne peut pas déterminer l'ordre de lecture réel sans indications supplémentaires. Dans les applications basées sur les vues, vous pouvez résoudre ces problèmes à l'aide des propriétés traversalBefore
et traversalAfter
.
À partir de Compose 1.5, Compose fournit une API tout aussi flexible, mais avec un nouveau modèle conceptuel.
isTraversalGroup
et traversalIndex
sont des propriétés sémantiques qui vous permettent de contrôler l'accessibilité et l'ordre de sélection de TalkBack dans les cas où l'algorithme de tri par défaut n'est pas approprié. isTraversalGroup
identifie les groupes sémantiquement importants, tandis que traversalIndex
ajuste l'ordre des éléments individuels au sein de ces groupes. Vous pouvez utiliser isTraversalGroup
seul ou avec traversalIndex
pour une personnalisation plus avancée.
Utilisez isTraversalGroup
et traversalIndex
dans votre application pour contrôler l'ordre de balayage du lecteur d'écran.
Regrouper des éléments avec isTraversalGroup
isTraversalGroup
est une propriété booléenne qui définit si un nœud sémantique est un groupe de balayage. Ce type de nœud a pour fonction de servir de limite ou de frontière pour organiser les enfants du nœud.
Si vous définissez isTraversalGroup = true
sur un nœud, tous les enfants de ce nœud sont visités avant de passer à d'autres éléments. Vous pouvez définir isTraversalGroup
sur les nœuds sélectionnables non compatibles avec les lecteurs d'écran, tels que les colonnes, les lignes ou les cases.
L'exemple suivant utilise isTraversalGroup
. Il émet quatre éléments de texte. Les deux éléments de gauche appartiennent à un seul élément CardBox
, tandis que les deux éléments de droite appartiennent à un autre élément 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 ) } }
Le code produit un résultat semblable à celui-ci:
Comme aucune sémantique n'a été définie, le comportement par défaut du lecteur d'écran consiste à balayer les éléments de gauche à droite et de haut en bas. En raison de cette valeur par défaut, TalkBack lit les fragments de phrases dans le mauvais ordre:
"Cette phrase est en" → "Cette phrase est" → "Colonne de gauche". → « à droite ».
Pour classer correctement les fragments, modifiez l'extrait d'origine en définissant isTraversalGroup
sur 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 } ) } }
Étant donné que isTraversalGroup
est défini spécifiquement sur chaque CardBox
, les limites des CardBox
s'appliquent lors du tri de leurs éléments. Dans ce cas, l'élément CardBox
gauche est lu en premier, suivi de l'élément CardBox
droit.
TalkBack lit maintenant les fragments de phrases dans le bon ordre:
"Cette phrase est dans" → "colonne de gauche". → "Cette phrase est" → "à droite".
Personnaliser davantage l'ordre de balayage
traversalIndex
est une propriété flottante qui vous permet de personnaliser l'ordre de balayage pour TalkBack. Si le regroupement d'éléments ne suffit pas pour que TalkBack fonctionne correctement, utilisez traversalIndex
conjointement avec isTraversalGroup
pour personnaliser davantage l'ordre des lecteurs d'écran.
La propriété traversalIndex
présente les caractéristiques suivantes:
- Les éléments avec des valeurs
traversalIndex
plus faibles sont prioritaires. - Elles peuvent être positives ou négatives.
- La valeur par défaut est
0f
. - N'affecte que les nœuds sélectionnables du lecteur d'écran, tels que les éléments à l'écran tels que le texte ou les boutons. Par exemple, définir uniquement
traversalIndex
sur une colonne n'aurait aucun effet, sauf siisTraversalGroup
est également défini sur la colonne.
L'exemple suivant montre comment utiliser traversalIndex
et isTraversalGroup
ensemble.
Exemple: balayage de l'affichage heure et statistiques
L'affichage heure et statistiques est un scénario courant dans lequel l'ordre de balayage standard ne fonctionne pas. L'exemple de cette section est un sélecteur d'heure, dans lequel un utilisateur peut parcourir les chiffres d'un affichage heure et statistiques et sélectionner des chiffres pour les tranches horaires et des minutes.
L'extrait simplifié suivant contient un CircularLayout
dans lequel 12 chiffres sont dessinés, en commençant par 12 et en se déplaçant dans le sens des aiguilles d'une montre autour du cercle:
@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()) } }
Comme l'affichage heure et statistiques n'est pas lu de manière logique avec l'ordre de gauche à droite et de haut en bas par défaut, TalkBack lit les chiffres dans le désordre. Pour résoudre ce problème, utilisez la valeur du compteur d'incrémentation, comme indiqué dans l'extrait de code suivant:
@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()) } }
Pour définir correctement l'ordre des balayages, commencez par définir CircularLayout
comme groupe de balayages et définissez isTraversalGroup = true
. Ensuite, lorsque le texte d'horloge est dessiné dans la mise en page, définissez son traversalIndex
correspondant sur la valeur du compteur.
Comme la valeur du compteur augmente continuellement, la traversalIndex
de chaque valeur d'horloge augmente à mesure que des nombres sont ajoutés à l'écran. La valeur d'horloge 0 a une valeur traversalIndex
de 0, et la valeur d'horloge 1 a une traversalIndex
de 1.
Dans ce cas, l'ordre dans lequel TalkBack les lit est défini. Les chiffres contenus dans CircularLayout
sont maintenant lus dans l'ordre attendu.
Étant donné que les traversalIndexes
définis ne se rapportent qu'aux autres index du même groupe, le reste de l'ordre de l'écran a été conservé. En d'autres termes, les modifications sémantiques indiquées dans l'extrait de code précédent ne modifient que l'ordre dans l'affichage heure et statistiques pour lequel isTraversalGroup = true
est défini.
Notez que si la sémantique CircularLayout's
n'est pas définie sur isTraversalGroup =
true
, les modifications de traversalIndex
s'appliquent toujours. Cependant, sans CircularLayout
pour les lier, les douze chiffres de l'affichage heure et statistiques sont lus en dernier, une fois que tous les autres éléments de l'écran ont été consultés. Cela est dû au fait que tous les autres éléments ont une traversalIndex
par défaut de 0f
et que les éléments de texte d'horloge sont lus après tous les autres éléments 0f
.
Exemple: Personnaliser l'ordre de balayage pour le bouton d'action flottant
Dans cet exemple, traversalIndex
et isTraversalGroup
contrôlent l'ordre de navigation d'un bouton d'action flottant Material Design. Cet exemple se base sur la mise en page suivante:
Par défaut, la mise en page de cet exemple présente l'ordre TalkBack suivant:
Barre d'application supérieure → Exemples de texte de 0 à 6 → bouton d'action flottant (FAB) → Barre d'application inférieure
Vous voudrez peut-être que le lecteur d'écran se concentre
d'abord sur le bouton d'action flottant. Pour définir un traversalIndex
sur un élément Material tel qu'un bouton d'action flottant:
@Composable fun FloatingBox() { Box(modifier = Modifier.semantics { isTraversalGroup = true; traversalIndex = -1f }) { FloatingActionButton(onClick = {}) { Icon(imageVector = Icons.Default.Add, contentDescription = "fab icon") } } }
Dans cet extrait, la création d'une zone avec isTraversalGroup
définie sur true
et traversalIndex
sur la même zone (-1f
est inférieure à la valeur par défaut de 0f
) signifie que la boîte flottante est placée avant tous les autres éléments à l'écran.
Vous pouvez ensuite placer la boîte flottante et d'autres éléments dans un échafaudage, qui implémente une mise en page Material Design:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun ColumnWithFABFirstDemo() { Scaffold( topBar = { TopAppBar(title = { Text("Top App Bar") }) }, floatingActionButtonPosition = FabPosition.End, floatingActionButton = { FloatingBox() }, content = { padding -> ContentColumn(padding = padding) }, bottomBar = { BottomAppBar { Text("Bottom App Bar") } } ) }
TalkBack interagit avec les éléments dans l'ordre suivant:
Bouton d'action flottant → Barre d'application supérieure → Exemples de texte 0 à 6 → Barre d'application inférieure
Ressources supplémentaires
- Accessibilité:concepts et techniques essentiels communs à tout le développement d'applications Android
- Créer des applications accessibles:étapes clés à suivre pour rendre votre application plus accessible
- Principes pour améliorer l'accessibilité des applications:principes clés à garder à l'esprit lorsque vous cherchez à rendre votre application plus accessible.
- Testing for Accessibility (Tests d'accessibilité) : principes et outils de test pour l'accessibilité sur Android.