Sebbene molte app Android TV siano sviluppate con componenti Android nativi, è importante considerare anche l'accessibilità di frame o componenti di terze parti, soprattutto quando si utilizzano le visualizzazioni personalizzate.
I componenti delle visualizzazioni personalizzate che si interfacciano 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 quando TalkBack è attivo:
- Lo stato attivo di accessibilità (un rettangolo verde) potrebbe non essere più visualizzato nell'app.
- L'impostazione Accessibilità potrebbe selezionare i confini dell'intero schermo.
- L'elemento attivo con requisiti di accessibilità potrebbe non essere spostabile.
- I quattro tasti di direzione del D-pad potrebbero non avere alcun effetto, anche se è in corso la gestione del codice.
Se rilevi uno di questi problemi nella tua app, verifica che
l'app mostri la sua struttura AccessibilityNodeInfo
ai servizi di accessibilità.
La parte rimanente di questa guida fornisce alcune soluzioni e best practice per risolvere questi problemi.
Gli eventi D-pad vengono utilizzati dai servizi di accessibilità
La causa principale di questo problema è che i servizi di accessibilità utilizzano gli eventi chiave.
Come illustrato nella figura 1, quando TalkBack è attivo, gli eventi del D-pad non vengono trasmessi al gestore del D-pad definito dallo sviluppatore. Al contrario, i servizi di accessibilità ricevono gli eventi chiave in modo da poter spostare l'attenzione sull'accessibilità. Poiché i componenti Android personalizzati non espongono per impostazione predefinita informazioni ai servizi di accessibilità sulla loro posizione sullo schermo, i servizi di accessibilità non possono spostare l'elemento attivo sull'accessibilità per evidenziarli.
Anche altri servizi di accessibilità sono interessati da questo problema: quando si usa Switch Access, potrebbero essere consumati anche gli eventi D-pad.
Poiché gli eventi D-pad vengono inviati ai servizi di accessibilità e questo servizio non sa dove si trovano i componenti UI in una vista personalizzata, devi implementare AccessibilityNodeInfo
affinché la tua app possa inoltrare correttamente gli eventi chiave.
Esporre le informazioni ai servizi di accessibilità
Per fornire ai servizi di accessibilità informazioni sufficienti sulla posizione e sulla descrizione delle viste personalizzate, implementa AccessibilityNodeInfo
per mostrare i dettagli di ogni componente.
Per definire la relazione logica delle viste in modo che i servizi di accessibilità possano gestire lo stato attivo, implementa ExploreByTouchHelper
e impostalo utilizzando ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat)
per le viste personalizzate.
Quando implementi ExploreByTouchHelper
, esegui l'override dei suoi 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 il video Google I/O 2013 - Abilitazione dell'accessibilità per persone cieche e ipovedenti su Android o leggi ulteriori informazioni sulla compilazione degli eventi di accessibilità.
Best practice
Obbligatorio:
AccessibilityNodeInfo.getBoundsInScreen()
deve definire la posizione del componente.Obbligatorio:
AccessibilityNodeInfo.setVisibleToUser()
deve riflettere la visibilità del componente.Obbligatorio:
AccessibilityNodeInfo.getContentDescription()
deve specificare la descrizione dei contenuti che TalkBack può annunciare.Specifica
AccessibilityNodeInfo.setClassName()
in modo che i servizi possano distinguere il tipo di componente.Quando implementi
performAction()
, rifletti l'azione utilizzando un elementoAccessibilityEvent
corrispondente.Per implementare altri tipi di azioni, come
ACTION_CLICK
, richiamaAccessibilityNodeInfo.addAction(ACTION_CLICK)
utilizzando la logica corrispondente inperformAction()
.Se applicabile, rispecchia lo stato del componente per
setFocusable()
,setClickable()
,setScrollable()
e metodi simili.Consulta la documentazione relativa a
AccessibilityNodeInfo
per identificare altri modi in cui i servizi di accessibilità possono interagire meglio con i componenti.
Anteprima
Consulta l'esempio di accessibilità con visualizzazione personalizzata per Android TV per conoscere le best practice per aggiungere il supporto dell'accessibilità alle app che utilizzano la visualizzazione personalizzata.