Bien que de nombreuses applications Android TV soient conçues 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 de vue 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 problèmes qui peuvent survenir lorsque Talkback est activé :
- Le focus d'accessibilité (un rectangle vert) peut disparaître dans votre application.
- Le focus d'accessibilité peut sélectionner la limite de l'écran entier.
- Le focus d'accessibilité peut ne pas être déplaçable.
- Les quatre touches directionnelles du pavé directionnel peuvent ne pas avoir d'effet, même si votre code les gère.
Si vous constatez l'un de ces problèmes dans votre application, vérifiez qu'elle expose son
AccessibilityNodeInfo arborescence aux services d'accessibilité.
Le reste de ce guide fournit quelques solutions et bonnes pratiques pour résoudre ces problèmes.
Les événements du pavé directionnel sont utilisés par les services d'accessibilité
La cause principale de ce problème est que les événements clés sont utilisés par les services d'accessibilité.
Comme illustré dans l'image 1, lorsque Talkback est activé, les événements du pavé directionnel ne sont pas transmis au gestionnaire de pavé directionnel défini par le développeur. Au lieu de cela, les services d'accessibilité reçoivent les événements clés afin de pouvoir déplacer le focus d'accessibilité. Étant donné que les composants Android personnalisés n'exposent pas par défaut d'informations aux services d'accessibilité concernant leur position à l'écran, les services d'accessibilité ne peuvent pas déplacer le focus d'accessibilité pour les mettre en surbrillance.
D'autres services d'accessibilité sont également concerné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 d'interface utilisateur dans une vue personnalisée, vous devez implémenter AccessibilityNodeInfo pour que votre application transmette correctement les événements clés.
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
exposer les détails de chaque composant. Pour définir la relation logique des vues
afin que les services d'accessibilité puissent gérer le focus, 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 Google I/O 2013 - Enabling Blind and Low-Vision Accessibility on Android ou découvrez comment populating accessibility events.
Bonnes pratiques
Obligatoire :
AccessibilityNodeInfo.getBoundsInScreen()doit définir la position du composant.Obligatoire :
AccessibilityNodeInfo.setVisibleToUser()doit refléter la visibilité du composant.Obligatoire :
AccessibilityNodeInfo.getContentDescription()doit spécifier la description du contenu que Talkback doit annoncer.Spécifiez
AccessibilityNodeInfo.setClassName()pour que les services puissent distinguer le type de composant.Lorsque vous implémentez
performAction(), reflétez l'action à l'aide d'un correspondantAccessibilityEvent.Pour implémenter d'autres types d'actions, tels que
ACTION_CLICK, appelezAccessibilityNodeInfo.addAction(ACTION_CLICK)à l'aide de la logique correspondante dansperformAction().Le cas échéant, reflétez l'état du composant pour
setFocusable(),setClickable(),setScrollable()et les méthodes similaires.Consultez la documentation de
AccessibilityNodeInfopour identifier d'autres façons dont les services d'accessibilité peuvent mieux interagir avec vos composants.
Exemples
Consultez l'exemple d'accessibilité des vues personnalisées pour Android TV afin de découvrir les bonnes pratiques pour ajouter une assistance d'accessibilité aux applications utilisant des vues personnalisées.