Le , par Laurent Cintas - Accessibilité
Temps de lecture estimé : 4 minutes.
Cet article décrit quelques principes fondamentaux pour intégrer l’accessibilité dans vos projets Flutter.
Les implémentations présentées dans ce document sont testées sur un environnement Android, avec Talkback 14.1 ou un clavier seul suivant les cas.
Nous vous proposons également en fin d’article une application de démonstration afin de tester ces différentes implémentations.
Sémantique des éléments
Chaque élément de l’interface utilisateur doit posséder une sémantique pertinente.
Cela inclut un rôle (exemple : bouton, lien, etc), un nom (exemple : fermer), et potentiellement un état (exemple : coché/décoché) et une valeur. Cette information est essentielle pour les technologies d’assistance comme les lecteurs d’écran.
Privilégier les Composants Natifs Flutter
L’utilisation de composants natifs Flutter/Material est fortement recommandée, la plupart d’entre eux intégrant déjà les propriétés d’accessibilités nécessaires.
Par exemple, le widget ElevatedButton
possède automatiquement un rôle de bouton, un élément CheckboxListTile
possède un rôle de case à cocher avec un état coché / décoché.
De plus, vous bénéficiez des mises à jour et améliorations continues de ces composants.
Widget Semantics
Lorsque les propriétés d’accessibilité ne sont pas nativement présentes, il est possible de surcharger un widget avec la classe Semantics
.
Ce widget permet d’ajouter les informations nécessaires à la compréhension des composants depuis une aide technique, et donc pallier d’éventuels défauts des composants natifs.
La classe Semantics
permet notamment de définir les rôles bouton (button:true
), lien (link:true
) ou entête (header:true
), ou encore les états coché (checked
), sélectionné (selected
).
Par exemple le code ci-dessous exposera les informations suivantes depuis Talkback : « Libellé, Bouton »
Semantics(
button: true,
child: const Text('Libellé')
)
Pour aller plus loin :
Gestion des focus
Dans un environnement applicatif mobile il est possible de gérer de manière décorrélée le focus du lecteur d’écran (accessibility focus) d’une part et le focus du clavier (input focus) d’autre part.
Accessibility focus (aide technique)
FocusSemanticEvent()
Dans certains cas le focus du lecteur est géré automatiquement par les composants Material (exemple : boîte de dialogue)
Cependant, pour des cas spécifiques comme par exemple la gestion d’erreurs dans un formulaire (en effet une règle pourrait être de positionner le focus dans le premier champ en erreur après soumission), vous pouvez utiliser FocusSemanticEvent()
pour manipuler le focus du lecteur d’écran.
L’accessibility focus peut être positionné sur des éléments focusables et non focusables.
Pour aller plus loin :
Input focus (clavier bluetooth)
FocusNode()
La classe FocusNode()
permet de gérer le focus du clavier.
Le focus peut être positionné sur des éléments focusables uniquement, possédant une propriété focusnode
(exemple : ElevatedButton
).
À noter que l’accessibility focus est également déplacé lors de l’utilisation de la méthode FocusNode()
. Pour autant ce n’est pas l’objectif initial de cette classe.
Pour aller plus loin : FocusNode class
Autofocus
La propriété autofocus
positionne le focus clavier sur un élément spécifique lors du chargement de la vue.
L’élément cible doit posséder une propriété autofocus
(exemple : ElevatedButton
, TextField
etc).
TextField(
autofocus: true,
decoration: InputDecoration(border: OutlineInputBorder(),labelText: 'Prénom')
)
Formulaires et Étiquettes
Utilisez les propriétés des composants de formulaire Flutter pour exposer clairement les noms des champs aux technologies d’assistance.
Par exemple, TextField
propose les propriétés label
et labelText
. Pour les cases à cocher et les boutons radio, utilisez la propriété title
.
TextField(
decoration: InputDecoration(label: Text('Email'))
)
TextField(
decoration: InputDecoration(labelText: 'Email')
)
Étiquettes et Aide à la Saisie
Lorsqu’une aide à la saisie est nécessaire, vous pouvez :
- Renseigner l’aide à la saisie dans l’étiquette :
TextField(
decoration: InputDecoration(
label: Text('Email (ex: prenom.nom@domaine.fr)')
)
)
- Utiliser la propriété
helperText
. Notez que cette information n’est pas automatiquement exposée lors de la prise de focus du champ. Il est nécessaire de doubler le texte dans la propriétéhint
pour une information complète dès la prise de focus.
Semantics(
hint: 'ex: prenom.nom@domaine.fr',
child: const TextField(
decoration: InputDecoration(
label: Text('Email'),
helperText: 'ex: prenom.nom@domaine.fr',
)
)
)
Notifications
Semantics.liveRegion
La propriété Semantics.liveRegion
permet de gérer une live region, similaire à l’attribut aria-live
dans un environnement web. Les contenus textuels mis à jour dynamiquement dans le widget sont automatiquement exposés par les aides techniques. La valeur true
a un comportement équivalent à aria-live="polite"
.
Semantics(
liveRegion: true,
child: Text(
'Quantité : $_counter',
)
)
Pour aller plus loin : Accessibility live region on Flutter
SemanticsService()
La classe SemanticsService()
permet de générer la vocalisation de messages indépendamment du contenu d’un widget.
void _incrementCounterService() {
setState(() {
_counterService++;
SemanticsService.announce(
"La quantité du produit est : $_counterService", TextDirection.ltr);
});
}
Pour aller plus loin : SemanticsService class
Application Démo
Retrouver plus d’exemples au sein de notre application démo sur Flutter : https://gitlab.com/temesis/app-flutter
Envie d’en savoir plus ?
Nous proposons deux formations dédiées à la mise en accessibilité d’une application Flutter :