Pourquoi l'accessibilité en Kotlin est un super-pouvoir, pas une simple case à cocher
\n\nImaginez : vous avez écrit une super application en Kotlin. Un beau Material Design, des animations fluides, des flux réactifs. Vous êtes fier de votre code. Mais ensuite, il s'avère qu'une personne malvoyante ne peut pas appuyer sur le bouton « Acheter », car TalkBack le lit comme « bouton non étiqueté ». Ou qu'un utilisateur avec un tremblement des mains rate le minuscule interrupteur.
\n\nL'accessibilité n'est pas une bureaucratie ennuyeuse. C'est faire en sorte que votre code Kotlin fonctionne pour tout le monde. Selon l'OMS, plus d'un milliard de personnes ont un handicap. Les ignorer, c'est perdre une audience et, honnêtement, être un mauvais développeur.
\n\nDans cet article, nous verrons comment écrire du code accessible en Kotlin sans douleur. Sans tonnes de code passe-partout. Avec des exemples concrets que vous pouvez copier-coller dès maintenant.
\n\nPrincipes de base : ContentDescription, votre meilleur ami
\n\nL'échec le plus fréquent en accessibilité est l'absence de description pour les éléments de l'interface. Le système TalkBack (lecteur d'écran sur Android) ne sait pas lire les images ou les icônes. Il a besoin de texte.
\n\nEn Kotlin, cela se fait via l'attribut contentDescription. Mais pas simplement « Bouton », plutôt de manière significative.
Mauvais exemple (à ne pas faire)
\nimageView.contentDescription = "Bouton"\n\nBon exemple
\nbinding.fabAddTask.contentDescription = "Ajouter une nouvelle tâche"\n\nSi l'icône est décorative (simple ornement) — définissez contentDescription = null pour que TalkBack l'ignore.
// Icône décorative — ne pas distraire l'utilisateur\nbinding.decorativeIcon.contentDescription = null\n\nConseil : Utilisez les ressources de chaînes (strings.xml) pour prendre en charge la localisation. Ne codez pas en dur le texte français dans les fichiers Kotlin.
Balisage sémantique : dire au système ce qui est important
\n\nLes View standards (Button, TextView) s'en sortent bien, mais les composants personnalisés cassent souvent l'accessibilité. En Kotlin, nous pouvons définir explicitement la sémantique.
Ajouter un rôle à l'élément
\nbinding.customView.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES\nbinding.customView.accessibilityDelegate = object : View.AccessibilityDelegate() {\n override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) {\n super.onInitializeAccessibilityNodeInfo(host, info)\n info.text = "Valeur actuelle : ${viewModel.value}"\n info.contentDescription = "Curseur de volume"\n }\n}\n\nCe code dit au système : « Hé, ce n'est pas juste un carré, c'est un curseur ! ». TalkBack comprendra que l'élément est interactif et pourra interagir correctement.
\n\nRegroupement d'éléments
\nSi vous avez une fiche produit avec une image, un prix et un nom — regroupez-les en un seul focus. Sinon, l'utilisateur écoutera trois éléments séparément.
\n\nbinding.cardProduct.apply {\n isFocusable = true\n contentDescription = "Produit : ${product.name}, prix : ${product.price} euros"\n}\n\nMaintenant, TalkBack lira toutes les informations en un seul clic.
\n\nNavigation par action : clavier et D-pad
\n\nTous les utilisateurs ne tapent pas sur l'écran avec le doigt. Certains utilisent un clavier (via OTG) ou un D-pad (télécommande). Votre application doit pouvoir être contrôlée sans contact.
\n\nEn Kotlin, cela se résout avec focusable et l'ordre de focus (nextFocusDown, nextFocusForward).
binding.buttonNext.nextFocusForwardId = R.id.buttonConfirm\nbinding.buttonConfirm.nextFocusDownId = R.id.buttonCancel\n\nVérifiez que tous les éléments interactifs reçoivent le focus. Une erreur fréquente est le TextView avec ClickableSpan (lien dans le texte). Par défaut, il ne reçoit pas le focus. Corrigeons cela :
binding.textWithLink.movementMethod = LinkMovement