Embora muitos apps para Android TV sejam criados com componentes nativos do Android, ele é também é importante considerar a acessibilidade frameworks ou componentes, especialmente ao usar visualizações personalizadas.
Os componentes de visualização personalizados que fazem a interface direta com o OpenGL ou o Canvas podem não funcionar bem com serviços de acessibilidade, como o TalkBack e o acesso com interruptor.
Considere alguns dos seguintes problemas que podem ocorrer ao usar o TalkBack em:
- O foco da acessibilidade (um retângulo verde) pode desaparecer do app.
- O foco de acessibilidade pode selecionar o limite de toda a tela.
- O foco de acessibilidade pode não ser móvel.
- As quatro teclas de direção do botão direcional podem não ter efeito, mesmo que o código as processe.
Se você notar algum desses problemas no seu app, verifique se o
o app expõe seu AccessibilityNodeInfo
aos serviços de acessibilidade.
O restante deste guia fornece algumas soluções e práticas recomendadas para lidar com esses problemas.
Eventos de botão direcional são consumidos pelos serviços de acessibilidade
A causa raiz desse problema é que os eventos principais são consumidos pela acessibilidade serviços.
Como ilustrado na figura 1, quando o TalkBack é ativado, os eventos do botão direcional não são passados para o manipulador D-pad definido pelo desenvolvedor. Em vez disso, os serviços de acessibilidade recebem os eventos-chave para que possam mover foco na acessibilidade. Como os componentes personalizados do Android não expõem por padrão, informações aos serviços de acessibilidade sobre a posição deles na tela; os serviços de acessibilidade não podem mover o foco da acessibilidade para destacá-los.
Outros serviços de acessibilidade são afetados de forma semelhante: eventos de botão direcional também podem ser consumida ao usar o acesso com interruptor.
Como os eventos D-pad são enviados para serviços de acessibilidade e
esse serviço não sabe onde estão os componentes da IU em uma visualização personalizada,
Implemente AccessibilityNodeInfo
para que seu app encaminhe o
eventos de teclas corretamente.
Expor informações aos serviços de acessibilidade
Fornecer aos serviços de acessibilidade informações suficientes sobre a
localização e descrição de visualizações personalizadas, implementar AccessibilityNodeInfo
para expor detalhes de cada componente.
Definir a relação lógica de visualizações para que os serviços de acessibilidade possam
gerenciar o foco, implementar ExploreByTouchHelper
e configurá-la usando
ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat)
para visualizações personalizadas.
Ao implementar ExploreByTouchHelper
, substitua os quatro métodos abstratos:
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)
Para mais detalhes, assista ao vídeo Google I/O 2013 - Capacitando pessoas cegas e com baixa visão Acessibilidade no Android (em inglês) ou leia mais sobre como preencher eventos de acessibilidade.
Práticas recomendadas
Obrigatório:
AccessibilityNodeInfo.getBoundsInScreen()
precisa definir a posição do componente.Obrigatório:
AccessibilityNodeInfo.setVisibleToUser()
precisa refletir a visibilidade do componente.Obrigatório:
AccessibilityNodeInfo.getContentDescription()
especifique a descrição do conteúdo para o Talkback anunciar.Especifique
AccessibilityNodeInfo.setClassName()
. para que os serviços possam distinguir o tipo do componente.Ao implementar o
performAction()
, reflita a ação usando umAccessibilityEvent
correspondente.Para implementar mais tipos de ação, como
ACTION_CLICK
, invoqueAccessibilityNodeInfo.addAction(ACTION_CLICK)
usando a lógica correspondente emperformAction()
.Quando aplicável, reflita o estado do componente para
setFocusable()
.setClickable()
,setScrollable()
, e métodos semelhantes.Analise a documentação de
AccessibilityNodeInfo
para identificar outras maneiras como os serviços de acessibilidade podem interagir melhor com seus componentes.
Exemplo
Consulte o exemplo de acessibilidade de visualização personalizada do Android TV para conferir as práticas recomendadas para: adicionar suporte à acessibilidade para apps que usam visualizações personalizadas.