Custom view accessibility support on Android TV

While many Android TV apps are built with native Android components, it's also important to consider the accessibility of third-party frameworks or components, especially when using custom views.

Custom view components interfacing directly with OpenGL or Canvas might not work well with accessibility services like Talkback and Switch Access.

Consider some of the following issues that might occur with Talkback switched on:

  • The accessibility focus (a green rectangle) might disappear in your app.
  • The accessibility focus might select the boundary of the whole screen.
  • The accessibility focus might not be movable.
  • The four direction keys on the D-pad might have no effect, even if your code is handling them.

If you observe any of these issues in your app, check that your app exposes its AccessibilityNodeInfo tree to the accessibility services.

The remainder of this guide provides some solutions and best practices to address these issues.

D-pad events are consumed by accessibility services

The root cause of this issue is that key events are consumed by accessibility services.

Dpad events consumption Figure 1. Diagrams depicting how the system functions with Talkback on and off.

As illustrated in figure 1, when Talkback is switched on, D-pad events are not passed to the D-pad handler defined by developer. Instead, accessibility services receive the key events so they can move the accessibility focus. Because custom Android components don't by default expose information to accessibility services about their position on the screen, accessibility services can't move the accessibility focus to highlight them.

Other accessibility services are similarly affected: D-pad events might also be consumed when using Switch Access.

Because D-pad events are submitted to accessibility services, and that service doesn't know where UI components are in a custom view, you must implement AccessibilityNodeInfo for your app to forward the key events correctly.

Expose information to accessibility services

To provide accessibility services with sufficient information about the location and description of custom views, implement AccessibilityNodeInfo to expose details for each component. To define the logical relationship of views so that accessibility services can manage focus, implement ExploreByTouchHelper and set it using ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat) for custom views.

When implementing ExploreByTouchHelper, override its four abstract methods:

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)

For more details, watch Google I/O 2013 - Enabling Blind and Low-Vision Accessibility on Android or read more about populating accessibility events.

Best practices

Sample

Consult the custom view accessibility sample for Android TV to see best practices for adding accessibility support to apps using custom views.