Élément Nesté Focusable
Ne volez pas le focus d'un parent cliquable en rendant un élément enfant focusable
Ce Que Nous Vérifions
Les éléments focusables ne doivent pas être imbriqués dans des éléments parents cliquables. Lorsqu'un élément enfant non interactif est focusable, la technologie d'assistance se concentre sur celui-ci au lieu du parent cliquable — ce qui signifie que le rôle interactif de l'élément n'est jamais annoncé.
Cette règle vérifie tous les contrôles d'accessibilité focusables qui ne sont pas eux-mêmes interactifs. Si un tel contrôle est contenu dans un parent cliquable, il est de fait interactif, mais n'annoncera pas de rôle. L'élément sera signalé comme une violation de l'accessibilité.
Exemple d'Échec ❌
La carte est cliquable, mais la photo de profil à l'intérieur est séparément focusable.
TalkBack n'annonce pas le rôle de la carte ou l'indication « Appuyez deux fois pour activer », et se concentre plutôt sur et annonce l'élément intérieur.
Les utilisateurs ne savent pas que la carte est interactive, et l'élément ayant le focus n'est pas cliquable.
Exemple Réussi ✅
L'élément intérieur n'est plus séparément focusable.
TalkBack se concentre sur la carte elle-même et annonce son contenu, son rôle, et "Appuyez deux fois pour activer".
Les utilisateurs comprennent que la carte est interactive et peuvent l'activer.
En Un Coup d'Œil
- Cette règle a un impact critique pour les utilisateurs de TalkBack et Voice Access
- Quand un élément enfant vole le focus d'un parent cliquable, le rôle interactif est perdu
- TalkBack n'annoncera pas "Appuyez deux fois pour activer" si l'élément en focus n'est pas lui-même cliquable
- La solution est toujours de supprimer la focusabilité de l'élément imbriqué, et non de lui ajouter un rôle
- Les vues conteneurs qui n'ont pas d'action ne devraient pas être laissées cliquables — cela évite les faux positifs
Impact sur les Utilisateurs
Quand la technologie d'assistance n'annonce pas un rôle, les utilisateurs aveugles ou malvoyants qui dépendent de TalkBack ne sauront pas qu'ils peuvent déclencher une action. Par exemple, TalkBack se concentre sur un élément intérieur et annonce uniquement son texte (par exemple "Thème"). Il n'annonce pas qu'il s'agit d'un bouton, ou que l'utilisateur doit appuyer deux fois pour activer. Les utilisateurs se retrouvent sans le contexte nécessaire pour interagir avec l'écran.
Confirmer le Problème d'Élément Nesté Focusable
- Activez TalkBack
- Concentrez-vous sur l'élément et chacun de ses descendants
- L'un des cas suivants se produira :
- Inaccessible : TalkBack lit le texte mais n'annonce pas un rôle ni une capacité d'interaction
- Accessible : TalkBack lit tout le texte et annonce également un rôle et/ou comment interagir avec l'élément
Résoudre les Problèmes
Supprimez la focusabilité des éléments imbriqués afin que le parent cliquable puisse recevoir le focus et annoncer son rôle. N'ajoutez pas de propriétés focusables aux descendants non interactifs d'une vue cliquable.
Pour éviter un faux positif, assurez-vous que les éléments conteneurs qui ne font rien lorsqu'ils sont tapés ne soient pas laissés cliquables. Nos outils ne peuvent pas déterminer si un élément cliquable a une action programmée associée, donc nous devons supposer que c'est le cas afin de signaler un comportement potentiellement inaccessible.
Examinez les éléments conteneurs environnants, tels que les Frame Layouts, Card Views ou Drawers, pour vous assurer que tout élément sans action associée n'est pas défini comme cliquable.
XML
Dans l'exemple ci-dessous, le MaterialCardView est cliquable, mais si l'un des enfants - LinearLayout ou TextView - possède focusable="true", TalkBack se concentrera sur celui-ci au lieu de la carte. Dans son état par défaut, la propriété focusable de LinearLayout et TextView est fausse. Assurez-vous qu'elle ne soit pas définie sur vrai, afin que la carte puisse recevoir le focus et annoncer son rôle interactif.
<com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/contact_name"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>Composer
Dans cet exemple, le Card est cliquable, mais si l'un des enfants - Row ou Text - possède un attribut .focusable(), TalkBack se concentrera dessus à la place. Assurez-vous que le Row ou Text n'ait pas un attribut .focusable(), afin que le Card puisse recevoir le focus, annoncer son contenu textuel et transmettre son rôle interactif (par exemple, "Appuyez deux fois pour activer").
Card(
modifier = Modifier
.clickable {
openContact(context)
}
) {
Row(
modifier = Modifier
.padding(10.dp),
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally)
) {
Text("Sarah Anderson")
}
}.NET MAUI
Dans l'exemple ci-dessous, la carte de contact Grid a un TapGestureRecognizer pour ouvrir le contact. Si un élément enfant à l'intérieur du Grid est indépendamment focusable, TalkBack se concentrera dessus au lieu de la carte. Assurez-vous qu'aucun élément enfant n'ait AutomationProperties.IsInAccessibleTree="true" défini explicitement, afin que le Grid conserve le focus et puisse annoncer "Appuyez deux fois pour activer".
<Grid
HorizontalOptions="FillAndExpand"
RowDefinitions="Auto,Auto"
RowSpacing="10"
VerticalOptions="FillAndExpand">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OpenContactCommand}"/>
</Grid.GestureRecognizers>
<Label
Grid.Row="1"
FontAttributes="Bold"
FontSize="16"
HorizontalOptions="CenterAndExpand"
VerticalOptions="FillAndExpand">
<Label.FormattedText>
<FormattedString>
<Span Text="Sarah Anderson"/>
</FormattedString>
</Label.FormattedText>
</Label>
</Grid>React Native
Dans cet exemple, la carte de contact est un TouchableOpacity avec des propriétés d'accessibilité définies directement dessus. Les propriétés accessible={true} et accessibilityRole="button" assurent que TalkBack annonce la carte comme un élément interactif. Aucune des vues enfants à l'intérieur ne devrait avoir accessible={true} défini indépendamment, car cela leur ferait voler le focus de la carte.
<TouchableOpacity
accessible={true}
accessibilityRole="button"
style={styles.contactCard}
onPress={() => openContact("sarah-anderson")}
>
<Text>Sarah Anderson</Text>
<Text>sarah@example.com</Text>
</TouchableOpacity>Flutter
Dans cet exemple, la carte de contact est un Card avec un InkWell gérant le tap. Si un widget enfant à l'intérieur du Card a sa propre Semantics enveloppe avec button: true ou onTap déterminé, TalkBack se concentrera sur lui au lieu de la carte. Gardez le gestionnaire de tap sur le InkWell et assurez-vous qu'aucun widget descendant ne réclame le focus indépendamment.
Card(
child: InkWell(
onTap: () => openContact(context, "sarah-anderson"),
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Sarah Anderson"),
Text("sarah@example.com"),
],
),
),
),
)Puis-je Ignorer Cette Règle ?
L'Élément Nesté Focusable a un impact critique pour les utilisateurs, et nous recommandons fortement de corriger ce problème. Quand le focus se pose sur un élément non interactif à l'intérieur d'un parent cliquable, les utilisateurs de TalkBack n'ont aucun moyen de savoir que l'élément peut être activé. Ignorer cette règle signifie que ces utilisateurs ne peuvent effectivement pas interagir avec l'élément concerné. En savoir plus sur ignorer les règles.
Ressources
Pages de Cours de Deque University
Remarque : Un abonnement est nécessaire pour un accès complet aux ressources de Deque University.
Autres ressources
- Directives pour l'accessibilité du contenu Web (WCAG) 2.1, Recommandation W3C
- Comprendre les WCAG 2.1
