Action Inaccessible
Assurez-vous que les éléments interactifs peuvent être activés avec VoiceOver
Ceci est une règle expérimentale, et donc son ou ses résultats sont considérés comme en phase de test bêta. En savoir plus sur règles expérimentales et comment vous pouvez aider à les améliorer.
Ce que nous vérifions
Un élément interactif doit pouvoir être activé par la technologie d'assistance. Cette règle vérifie que l'action associée à un élément interactif peut être ciblée et déclenchée en utilisant VoiceOver.
Exemple d'échec ❌
VoiceOver peut focus le bascule des 'Notifications' mais cannot activate it
VoiceOver annonce "Notifications, on." - aucun rôle ou indice d'activation n'est fourni
Le double-tap ne fait rien ; les utilisateurs n'ont aucun moyen de basculer le paramètre
Exemple de réussite ✅
VoiceOver peut focus and activate le bascule des 'Notifications'
VoiceOver annonce "Notifications, switch button, on. Double-tap to activate."
Le rôle et l'indice d'activation sont présents ; les utilisateurs savent exactement comment interagir avec le contrôle
En Bref
- Cette règle a un impact critique pour les utilisateurs
- Cette règle signale les éléments interactifs sur lesquels VoiceOver ne peut se concentrer ni activer
- Cela se produit lorsqu'un élément n'est pas focalisable en lui-même et n'est pas à l'intérieur d'un parent focalisable
- Un élément interactif qui est à l'intérieur d'un parent focalisable est inaccessible lorsqu'aucune action, reconnaisseur de gestes, ou point d'activation n'est détecté
Impact sur les utilisateurs
Les utilisateurs de technologies d'assistance sont les plus impactés. Lorsque VoiceOver peut se concentrer sur un élément interactif mais ne peut pas l'activer, les utilisateurs peuvent être incapables de réaliser des actions critiques - telles que soumettre un formulaire, basculer un paramètre ou naviguer vers un autre écran. Cela crée une barrière totale pour les personnes qui dépendent entièrement de VoiceOver pour interagir avec l'application.
Confirmer le problème d'action inaccessible
- Activez VoiceOver
- Concentrez-vous sur l'élément
- L'une des situations suivantes se produira :
- Inaccessible : L'utilisateur ne pourra pas activer l'élément en utilisant VoiceOver
- Accessible : L'utilisateur pourra utiliser VoiceOver pour activer l'élément
Résoudre les problèmes
Il existe divers scénarios pouvant entraîner un problème d'action inaccessible. La solution dépend de la façon dont l'élément est structuré. Passez en revue les approches ci-dessous et utilisez celle qui correspond à votre mise en page.
UIKit
Il existe plusieurs approches, selon la façon dont l'élément est structuré.
Corriger dans Storyboard — assurez-vous que le contrôle actif est un élément d'accessibilité :
- Sélectionnez l'élément avec un problème de
InaccessibleAction. - Assurez-vous que le panneau Inspecteurs est visible.
- Sélectionnez le Inspecteur d'identité.
- Sous Accessibilité, assurez-vous que la case "Activé" est cochée pour le contrôle actif.
Une option alternative est de changer le parcours d'accessibilité de l'élément :
- Répétez les étapes 1 à 3 pour le contrôle actif, son étiquette et l'élément contenant.
- Assurez-vous que la case "Activé" est cochée uniquement pour le contrôle actif, pas pour l'étiquette ou l'élément contenant.
- Dans le code, mettez à jour le parcours d'accessibilité pour inclure à la fois l'étiquette et le contrôle actif (voir la solution de parcours d'accessibilité dans le code ci-dessous).
Une autre solution consiste à centrer le contrôle actif au sein de son parent pour que le point d'activation par défaut de VoiceOver puisse l'atteindre :
- Sélectionnez l'élément avec un problème de
InaccessibleAction. - Assurez-vous que le panneau Inspecteurs est visible.
- Sélectionnez le contrôle actif.
- Sélectionnez le Inspecteur de taille.
- Assurez-vous que le contrôle actif est centré horizontalement et verticalement dans l'élément qui le contient.
Corriger dans le code :
Assurez-vous que le isAccessibilityElement du contrôle actif est réglé sur true :
buttonContainerView.isAccessibilityElement = trueAjoutez un détecteur de geste à la vue contenant :
buttonContainerView.addGestureRecognizer(UITapGestureRecognizer(target: self, selector: #selector(buttonTapped)))Centrez le contrôle actif dans la vue parente pour que le accessibilityActivationPoint de VoiceOver déclenche son action :
buttonContainerView.button.centerXAnchor.constraint(equalTo: buttonContainerView.centerXAnchor).isActive = true
buttonContainerView.button.centerYAnchor.constraint(equalTo: buttonContainerView.centerYAnchor).isActive = trueMettez à jour le chemin d'accessibilité pour inclure à la fois l'étiquette et le contrôle actif.
Définissez isAccessibilityElement=false sur l'étiquette et l'élément parent, pour que seul le contrôle lui-même (le toggle dans ce cas) soit un élément d'accessibilité.
// 1. Only the toggle should be an accessibility element
toggleContainerView.toggle.isAccessibilityElement = true
toggleContainerView.label.isAccessibilityElement = false
toggleContainerView.isAccessibilityElement = false
// 2. Expand the toggle's accessibilityPath to encompass the full container
// so VoiceOver's focus ring covers both the label and the toggle
let containerFrame = toggleContainerView.superview!.convert(toggleContainerView.frame, to: toggleContainerView.superview)
toggleContainerView.toggle.accessibilityPath = UIBezierPath(rect: containerFrame)SwiftUI
Ce problème ne se produit pas sur la plupart des éléments et contrôles par défaut dans SwiftUI, mais peut survenir avec des contrôles personnalisés ou lorsque des éléments sont regroupés incorrectement.
Lors de la création de contrôles personnalisés qui imitent le comportement d'un pas à pas, curseur ou interrupteur, utilisez .accessibilityRepresentation pour donner au contrôle personnalisé le même comportement d'accessibilité que son homologue standard :
// Add .accessibilityRepresentation on a custom Toggle view
HStack {
Text("Dark mode is \(getDarkModeStatus().localized)")
Image(systemName: getDarkModeImage())
}.onTapGesture {
isOn.toggle()
}
.accessibilityRepresentation {
Toggle(isOn: $isOn, label: {
Text("Dark mode is \(getDarkModeStatus().localized)")
})
}Lors du regroupement des vues, utilisez .accessibilityElement(children: .combine) ou .accessibilityElement(children: .contain) pour garantir que toutes les actions sur les contrôles enfants restent accessibles :
VStack(alignment: .leading) {
Text("Adjust settings below")
.accessibilityElement(children: .ignore)
Divider()
Toggle(isOn: $isOn) {
Text("Dark Mode is \(toggleStateText())")
}
.accessibility(value: Text("Dark Mode is \(toggleStateText())"))
}
.accessibilityElement(children: .combine)
.accessibilityLabel(Text("Adjust settings below"))Si la vue contenant a un contrôle ajustable comme un pas à pas ou un curseur, utilisez .accessibilityAdjustableAction pour offrir la meilleure expérience d'accessibilité :
VStack {
Text("Adjust the stepper below to update dog petting data".localized)
Divider()
HStack {
Stepper(value: $value) {
Text("Total dogs pet today \($value.wrappedValue)")
}.accessibilityElement(children: .ignore)
}
}
.accessibilityElement(children: .combine)
.accessibilityValue(Text("\($value.wrappedValue)"))
.accessibilityAdjustableAction({ direction in
switch direction {
case .increment:
value += 1
case .decrement:
value -= 1
@unknown default:
print("unknown direction used")
}
})React Native
Ce problème est rare pour les contrôles tactiles ou pressables standard dans React Native, mais peut survenir avec des contrôles personnalisés.
Option 1 : Permettez à la vue parente de gérer le focus
Définissez la propriété accessible de la vue parente sur true et accessibilityElementsHidden sur false, et assignez le accessibilityRole approprié :
<View
accessible={true}
accessibilityElementsHidden={false}
accessibilityRole='link'
accessibilityLabel='Learn more about Deque'
onTouchStart={openLink}
>
<Image
source={DequeLogo}
style={{ width: 100, height: 100 }}
/>
</View>Option 2 : Permettez à l'élément lui-même de gérer le focus
Réglez accessible, accessibilityElementsHidden et accessibilityRole directement sur le contrôle :
<Image
source={DequeLogo}
accessible={true}
accessibilityElementsHidden={false}
accessibilityRole='link'
accessibilityLabel='Learn more about Deque'
onTouchStart={openLink}
style={{ width: 100, height: 100 }}
/>Flutter
Les widgets Material de Flutter (ElevatedButton, IconButton, etc.) exposent automatiquement les actions de tapotement au lecteur d'écran. Lors de la création d'éléments interactifs personnalisés avec GestureDetector, enveloppez-les dans MergeSemantics avec un widget Semantics pour garantir que le lecteur d'écran puisse découvrir et activer l'élément en un seul arrêt de focus.
MergeSemantics(
child: Semantics(
button: true,
label: 'Archive item',
child: GestureDetector(
onTap: () {},
child: Container(
padding: const EdgeInsets.all(12.0),
color: Colors.green.shade100,
child: const Text('Archive item'),
),
),
),
)Puis-je ignorer cette règle ?
Une Action inaccessible a un Impact critique pour les utilisateurs, et nous recommandons fortement de corriger ces problèmes. Comme il s'agit d'une règle expérimentale, vous devriez vérifier les résultats manuellement. Si vous avez confirmé que l'élément est activable par VoiceOver, il peut être acceptable d'ignorer cette découverte. En savoir plus sur ignorer les règles.
Ressources
Pages de cours de l'Université Deque
Remarque : L'accès complet aux ressources de l'Université Deque nécessite un abonnement.
Autres ressources
- Lignes directrices pour l'accessibilité du contenu Web (WCAG) 2.1, Recommandation W3C
- WCAG 2.1 Documents de compréhension
