Supporto dell'accessibilità della visualizzazione personalizzata su Android TV

Sebbene molte app per Android TV siano create con componenti Android nativi, è anche importante considerare l'accessibilità di framework o componenti di terze parti, soprattutto quando si utilizzano visualizzazioni personalizzate.

I componenti di visualizzazione personalizzata che interagiscono direttamente con OpenGL o Canvas potrebbero non funzionare correttamente con i servizi di accessibilità come TalkBack e Switch Access.

Considera alcuni dei seguenti problemi che potrebbero verificarsi con TalkBack attivato:

  • Lo stato attivo per l'accessibilità (un rettangolo verde) potrebbe scomparire nella tua app.
  • Lo stato attivo per l'accessibilità potrebbe selezionare il bordo dell'intero schermo.
  • Lo stato attivo per l'accessibilità potrebbe non essere spostabile.
  • I quattro tasti direzionali del D-pad potrebbero non avere alcun effetto, anche se il codice li gestisce.

Se riscontri uno di questi problemi nella tua app, verifica che l'app esponga il relativo AccessibilityNodeInfo albero ai servizi di accessibilità.

Il resto di questa guida fornisce alcune soluzioni e best practice per risolvere questi problemi.

Gli eventi del D-pad vengono utilizzati dai servizi di accessibilità

La causa principale di questo problema è che gli eventi chiave vengono utilizzati dai servizi di accessibilità.

Utilizzo degli eventi D-pad e TalkBack
Figura 1. Diagrammi che mostrano come funziona il sistema con TalkBack attivo e disattivo.

Come illustrato nella Figura 1, quando TalkBack è attivo, gli eventi del D-pad non vengono passati al gestore del D-pad definito dallo sviluppatore. Al contrario, i servizi di accessibilità ricevono gli eventi chiave in modo da poter spostare lo stato attivo per l'accessibilità. Poiché i componenti Android personalizzati non espongono per impostazione predefinita le informazioni ai servizi di accessibilità sulla loro posizione sullo schermo, i servizi di accessibilità non possono spostare lo stato attivo per l'accessibilità per evidenziarli.

Anche altri servizi di accessibilità sono interessati in modo simile: gli eventi del D-pad potrebbero essere utilizzati anche quando si utilizza Switch Access.

Poiché gli eventi del D-pad vengono inviati ai servizi di accessibilità e questo servizio non sa dove si trovano i componenti dell'interfaccia utente in una visualizzazione personalizzata, devi implementare AccessibilityNodeInfo per la tua app in modo che inoltri correttamente gli eventi chiave.

Esporre informazioni ai servizi di accessibilità

Per fornire ai servizi di accessibilità informazioni sufficienti sulla posizione e sulla descrizione delle visualizzazioni personalizzate, implementa AccessibilityNodeInfo per esporre i dettagli di ogni componente. Per definire la relazione logica delle visualizzazioni in modo che i servizi di accessibilità possano gestire lo stato attivo, implementa ExploreByTouchHelper e impostalo utilizzando ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat) per le visualizzazioni personalizzate.

Quando implementi ExploreByTouchHelper, esegui l'override dei quattro metodi astratti:

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)

Per maggiori dettagli, guarda Google I/O 2013 - Enabling Blind and Low-Vision Accessibility on Android o leggi ulteriori informazioni su come popolare gli eventi di accessibilità.

Best practice

Esempio

Consulta l'esempio di accessibilità delle visualizzazioni personalizzate per Android TV per scoprire le best practice per aggiungere il supporto per l'accessibilità alle app che utilizzano visualizzazioni personalizzate.