Accessibilité des affichages personnalisés sur Android TV

Bien que de nombreuses applications Android TV soient créées avec des composants Android natifs, il est également important de tenir compte de l'accessibilité des frameworks ou composants tiers, en particulier lorsque vous utilisez des vues personnalisées.

Les composants d'affichage personnalisés qui interagissent directement avec OpenGL ou Canvas peuvent ne pas fonctionner correctement avec les services d'accessibilité tels que TalkBack et Switch Access.

Voici quelques-uns des problèmes qui peuvent survenir lorsque TalkBack est activé:

  • Le ciblage de l'accessibilité (rectangle vert) peut disparaître de votre application.
  • Le ciblage d'accessibilité peut sélectionner les limites de la totalité de l'écran.
  • Il est possible que le curseur d'accessibilité ne puisse pas être déplacé.
  • Les quatre touches de direction du pavé directionnel peuvent n’avoir aucun effet, même si votre code les gère.

Si vous observez l'un de ces problèmes dans votre application, vérifiez qu'elle expose son arborescence AccessibilityNodeInfo aux services d'accessibilité.

Le reste de ce guide fournit des solutions et des bonnes pratiques permettant de résoudre ces problèmes.

Les événements du pavé directionnel sont utilisés par les services d'accessibilité

La cause première de ce problème est que les événements de touche sont utilisés par les services d'accessibilité.

Consommation d'événements du pavé directionnel Figure 1. Schémas illustrant le fonctionnement du système lorsque TalkBack est activé et désactivé

Comme l'illustre la figure 1, lorsque TalkBack est activé, les événements du pavé directionnel ne sont pas transmis au gestionnaire du pavé directionnel défini par le développeur. À la place, les services d'accessibilité reçoivent les événements de touche afin de pouvoir déplacer le ciblage de l'accessibilité. Étant donné que, par défaut, les composants Android personnalisés n'exposent pas d'informations aux services d'accessibilité concernant leur position à l'écran, les services d'accessibilité ne peuvent pas déplacer le curseur d'accessibilité pour les mettre en évidence.

Les autres services d'accessibilité sont également affectés: les événements du pavé directionnel peuvent également être utilisés lorsque vous utilisez Switch Access.

Étant donné que les événements du pavé directionnel sont envoyés aux services d'accessibilité et que ce service ne sait pas où se trouvent les composants de l'interface utilisateur dans une vue personnalisée, vous devez implémenter AccessibilityNodeInfo pour que votre application transfère correctement les événements de touche.

Exposer des informations aux services d'accessibilité

Pour fournir aux services d'accessibilité suffisamment d'informations sur l'emplacement et la description des vues personnalisées, implémentez AccessibilityNodeInfo pour afficher les détails de chaque composant. Pour définir la relation logique des vues afin que les services d'accessibilité puissent gérer le ciblage, implémentez ExploreByTouchHelper et définissez-le à l'aide de ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat) pour les vues personnalisées.

Lorsque vous implémentez ExploreByTouchHelper, remplacez ses quatre méthodes abstraites:

Kotlin

// Return the virtual view ID whose view is covered by the input point (x, y).
protected fun getVirtualViewAt(x: Float, y: Float): Int

// Fill the virtual view ID list into the input parameter virtualViewIds.
protected fun getVisibleVirtualViews(virtualViewIds: List<Int>)

// For the view whose virtualViewId is the input virtualViewId, populate the
// accessibility node information into the AccessibilityNodeInfoCompat parameter.
protected fun onPopulateNodeForVirtualView(virtualViewId: Int, @NonNull node: AccessibilityNodeInfoCompat)

// Set the accessibility handling when perform action.
protected fun onPerformActionForVirtualView(virtualViewId: Int, action: Int, @Nullable arguments: Bundle): Boolean

Java

// Return the virtual view ID whose view is covered by the input point (x, y).
protected int getVirtualViewAt(float x, float y)

// Fill the virtual view ID list into the input parameter virtualViewIds.
protected void getVisibleVirtualViews(List<Integer> virtualViewIds)

// For the view whose virtualViewId is the input virtualViewId, populate the
// accessibility node information into the AccessibilityNodeInfoCompat parameter.
protected void onPopulateNodeForVirtualView(int virtualViewId, @NonNull AccessibilityNodeInfoCompat node)

// Set the accessibility handling when perform action.
protected boolean onPerformActionForVirtualView(int virtualViewId, int action, @Nullable Bundle arguments)

Pour en savoir plus, regardez la vidéo Google I/O 2013 - Enable Blind and Low-Vision Accessibility on Android (Google I/O 2013 : activer l'accessibilité pour les personnes non voyantes et malvoyantes sur Android) ou découvrez comment remplir les événements d'accessibilité.

Bonnes pratiques

Exemples

Consultez l'exemple d'accessibilité des vues personnalisées pour Android TV afin de connaître les bonnes pratiques pour ajouter une prise en charge de l'accessibilité aux applications utilisant des vues personnalisées.