4

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?

4

2 回答 2

2

OP 我不知道你的替代方法是什么,但这对我有用:

ViewCompat.setAccessibilityDelegate(mySecondView, new AccessibilityDelegateCompat() {
    @Override
    public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) {
        super.onInitializeAccessibilityNodeInfo(v, info);
        info.setTraversalAfter(myFirstView);
    }
});

但是我没有在 API 22 之前的任何东西上测试它,@alanv 声称这不起作用,但我找不到任何东西来支持他的说法。

于 2017-02-14T00:46:55.633 回答
1

调用AccessibilityNodeInfoCompat.setTraversalBefore/After对 API < 22 没有影响。该功能未向后移植。

只需在以下位置拨打电话即可获得相同的效果Build.VERSION.SDK_INT >= 22

public static void setAccessibilityTraversalAfter(View view, int afterId) {
  if (Build.VERSION.SDK_INT >= 22) {
    view.setAccessibilityTraversalAfter(afterId);
  }
}
于 2017-01-14T01:53:20.797 回答