Skip to content

Virtual accessibility node hierarchies

ZieIony edited this page Nov 5, 2020 · 1 revision

An accessibility node tree can match its corresponding view hierarchy, but it doesn't have to. Certain complex views, like a chart, can draw their items directly on Canvas, and handle input events without any additional view hierarchy. Such a view should provide a virtual accessibility node hierarchy to expose its internal structure to the accessibility framework. Accessibility nodes can be provided directly by the view or using an AccessibilityDelegate object.

While implementing a custom AccessibilityNodeInfo hierarchy is possible, it can be a quite frustrating and time-consuming task because of the lacking documentation, lots of details, and a very specific testing process. A much easier approach involves using ExploreByTouchHelper and implementing a couple of methods used to generate nodes, handle events, and respond to touch exploration. Setup is very simple and provided by the documentation:

class MyCustomView extends View {
    private MyExploreByTouchHelper mExploreByTouchHelper;

    public MyCustomView(Context context) {
         mExploreByTouchHelper = new MyExploreByTouchHelper(this);
         ViewCompat.setAccessibilityDelegate(this, mExploreByTouchHelper);
    }

    @Override
    public boolean dispatchHoverEvent(MotionEvent event) {
        return mHelper.dispatchHoverEvent(this, event)
           || super.dispatchHoverEvent(event);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        return mHelper.dispatchKeyEvent(event)
           || super.dispatchKeyEvent(event);
    }

    @Override
    public void onFocusChanged(boolean gainFocus, int direction,
        Rect previouslyFocusedRect) {
        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
        mHelper.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
    }
}

Then you have to implement the abstract methods of the helper:

  • int getVirtualViewAt(float x, float y) to return a virtual child when found by the touch exploration,
  • void getVisibleVirtualViews(List<Integer> virtualViewIds) to populate the list of children,
  • void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfoCompat node) to fill the node structure for a child,
  • and boolean onPerformActionForVirtualView(int virtualViewId, int action, Bundle arguments) to perform an action on the virtual child.

An example implementation can be found here.

Clone this wiki locally