I'm trying to programmatically setAccessibilityTraversalOrder on a view in Android and it's working great for API level 22. I have a method, which I call to set the traversal order.
@TargetApi(22)
public static void setAccessibilityAfter(View view, int afterId) {
view.setAccessibilityTraversalAfter(afterId);
}
And then I set an AccessibilityDelegate like this.
private static final AccessibilityDelegateCompat ACCESSIBILITY_DELEGATE_COMPAT =
new AccessibilityDelegateCompat() {
@Override
public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(host, event);
event.setClassName(Button.class.getName());
}
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
super.onInitializeAccessibilityNodeInfo(host, info);
info.setClassName(Button.class.getName());
}
};
I need to support minimum API version of 16 (JellyBean), thus this solution doesn't scale. So, I found out about AccessibilityNodeInfoCompat class. I tried to use that class like this in my helper method like this.
public static void setAccessibilityAfter(View view, int afterId) {
AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(view);
ViewCompat.onInitializeAccessibilityNodeInfo(view, info);
if (afterId != View.NO_ID) {
View rootView = view.getRootView();
if (rootView == null) {
rootView = view;
}
View next = rootView.findViewById(afterId);
if (next != null) {
info.setTraversalAfter(next);
}
}
}
There are 2 problems with this solution: 1: It doesn't work because as soon as a user touches that view on the screen, the delegate gets called again and initializes that node again, so I lose the traversalAfter value I set here. 2: I'm also leaking a node here, which I'm not sure when to recycle.
Can anybody help me how I can hook Android backwards compatibility using NodeInfoCompat and AccessibilityDelegateCompat?