L'accessibilité sur Android en 2026 : une checklist TalkBack et sémantique Compose qui tient la route
Une checklist pratique d'accessibilité Android pour 2026 — TalkBack, sémantique Compose, zones tactiles et la passe de test que je fais sur chaque écran avant publication.
L’accessibilité sur Android est souvent traitée comme un point de checklist avant publication, casé après que l’UI soit « terminée ». Cet ordre est à l’envers, et ça se voit : un écran construit sans penser à la sémantique prend des heures à corriger a posteriori, alors que le même écran construit avec la sémantique dès le départ ne coûte presque rien de plus. Voici la checklist que j’applique réellement — pas un document de politique, une liste de choses que je fais en écrivant l’UI Compose, plus la passe de test avant toute publication.
Pourquoi corriger après coup coûte cher, et construire dès le départ non
TalkBack, le lecteur d’écran d’Android, ne lit pas les pixels — il lit l’arbre sémantique que Compose génère en parallèle de votre UI. Si vous n’y pensez jamais en écrivant un écran, TalkBack finit par lire des détails d’implémentation bruts : un bouton avec seulement une icône s’annonce comme « Bouton », une image décorative s’annonce comme « Image », et une ligne de trois composables séparés s’annonce comme trois arrêts séparés au lieu d’une seule phrase. Corriger ça après coup signifie repasser sur chaque composable en se demandant « qu’est-ce que ça devrait vraiment dire », ce qui est plus lent que de se poser la même question la première fois.
La solution consiste à traiter la sémantique comme faisant partie de l’API du composant, pas comme une réflexion après-coup accrochée à la fin de la chaîne de Modifier.
La checklist
1. Chaque contrôle non textuel a un contentDescription — ou aucun
Si un bouton a un texte visible, n’ajoutez pas de description redondante — TalkBack lit déjà le texte, et une description dupliquée le fait lire deux fois. Si un bouton n’a qu’une icône, la description est obligatoire :
IconButton(onClick = { onDelete(item.id) }) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = stringResource(R.string.delete_item, item.name)
)
}
Les images purement décoratives reçoivent explicitement contentDescription = null. Une image sans description du tout est quand même annoncée comme « image sans étiquette », ce qui est pire que le silence.
2. Regrouper le contenu lié avec mergeDescendants
Une carte avec un titre, un sous-titre et un badge se lit par défaut comme trois arrêts TalkBack séparés, ce qui veut dire trois balayages pour entendre une seule ligne. Enveloppez le groupe pour qu’il s’annonce comme une seule unité :
Row(
modifier = Modifier.semantics(mergeDescendants = true) {}
) {
Text(title)
Text(subtitle)
Badge { Text(status) }
}
Testez ça en activant TalkBack et en balayant l’écran une fois. Si une seule ligne logique prend plus d’un balayage, elle a besoin d’être fusionnée.
3. Les zones tactiles font 48dp, pas la taille visuelle de l’icône
Une icône de 24dp sans marge est une zone tactile de 24dp, ce qui échoue à la fois aux directives d’accessibilité et à l’utilisabilité de base pour quiconque a une dextérité réduite. Modifier.minimumInteractiveComponentSize() gère ça dans Compose actuel sans calcul manuel de marge — appliquez-le à chaque icône tapable, pas seulement celles qui semblent serrées en revue.
4. Ne communiquez pas un état uniquement par la couleur
Une bordure rouge sur un champ invalide est invisible pour un utilisateur daltonien et non annoncée pour un utilisateur TalkBack. Associez chaque signal uniquement coloré à un changement de texte ou d’icône : un message d’erreur sous le champ, une icône d’erreur à côté du label. C’est aussi simplement une meilleure UX pour un utilisateur voyant qui regarde rapidement — la couleur seule demande plus d’attention à interpréter qu’un mot.
5. Des zones actives pour le contenu qui change sans clic
Si un total se met à jour après que l’utilisateur tape un montant, TalkBack ne le remarquera pas à moins que le composable soit marqué comme zone active :
Text(
text = "Total : $formattedTotal",
modifier = Modifier.semantics { liveRegion = LiveRegionMode.Polite }
)
Polite attend que l’annonce en cours se termine ; Assertive interrompt. Utilisez Assertive avec parcimonie — pour une erreur qui demande une attention immédiate, pas pour un total qui défile.
La passe de test
La revue de code n’attrape sans doute que la moitié de ce qui compte vraiment, parce que la plupart de ces problèmes ne sont évidents qu’avec le lecteur d’écran activé. Avant de publier un écran, je fais trois vérifications :
- TalkBack, en balayant tout l’écran avec l’affichage éteint, en écoutant seulement. Si je ne peux pas dire ce que fait un contrôle rien qu’à l’annonce, il a besoin d’une meilleure description.
- Accessibility Scanner (l’application autonome de Google) pour la taille des zones tactiles et le contraste — il signale les deux automatiquement et pointe le composable exact.
- Échelle de police à 200 % dans les réglages système. Un texte qui tronque, se chevauche ou se coupe à cette échelle est un bug, pas un cas limite — une part significative des utilisateurs réels utilise en permanence des échelles de police élevées.
Ça compte plus pour certaines applications que pour d’autres. OldSchool, l’application de rappel de médicaments, s’adresse à un public plus âgé pour qui des échelles de police plus grandes et les lecteurs d’écran ne sont pas des cas limites du tout — ils sont plutôt la médiane. Avoir construit la checklist dans la bibliothèque de composants une seule fois m’a évité de devoir la redériver écran par écran à mesure que l’application grandissait.
Ce qu’il faut retenir
Le travail d’accessibilité fait en fin de projet est coûteux parce qu’il est correctif — quelqu’un doit remarquer l’écart, puis repasser corriger chaque écran individuellement. Le travail d’accessibilité fait en écrivant chaque composable est proche de gratuit, parce que les questions (« comment ça s’annonce », « est-ce un arrêt ou trois », « la zone tactile est-elle réelle ») se répondent en quelques secondes pendant qu’on regarde déjà le code. Traitez la checklist comme une habitude pour les nouveaux écrans, pas comme un exercice d’urgence de la semaine de sortie, et elle cesse d’être une checklist du tout.
// À lire aussi
D’autres notes du journal
L'API In-App Review d'Android : demander une note sans être pénible
Un guide pratique de l'API In-App Review de Google — comment elle fonctionne réellement, quand la déclencher, et pourquoi la popup classique « notez-nous » nuit discrètement à votre note sur le Play Store.
Raccourcis d'application et tuiles de Paramètres rapides sur Android : enregistrer de l'eau sans ouvrir l'application
Un guide pratique de l'API dynamique ShortcutManager et de TileService sur Android — comment permettre à une action en un tap de contourner complètement l'application, avec les pièges qui font trébucher la plupart des implémentations.
Les types de services au premier plan sur Android en 2026 : choisir celui auquel votre fonctionnalité correspond vraiment
Un guide pratique des restrictions de types de services au premier plan d'Android — dataSync, mediaPlayback, specialUse, shortService — et comment choisir le bon sans se faire tuer ou rejeter.