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à.
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
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 deve annunciare.Specifica
AccessibilityNodeInfo.setClassName()in modo che i servizi possano distinguere il tipo di componente.Quando implementi
performAction(), rifletti l'azione utilizzando un corrispondenteAccessibilityEvent.Per implementare altri tipi di azioni, ad esempio
ACTION_CLICK, richiamaAccessibilityNodeInfo.addAction(ACTION_CLICK)utilizzando la logica corrispondente inperformAction().Se applicabile, rifletti lo stato del componente per
setFocusable(),setClickable(),setScrollable()e metodi simili.Consulta la documentazione di
AccessibilityNodeInfoper identificare altri modi in cui i servizi di accessibilità possono interagire meglio con i tuoi componenti.
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.