7

I have some TextViews that I would like to announce as a header or a link in Talkback mode. Currently, it just announces the text inside the TextView, but I would like it to say "Heading" afterwards, or "link" depending on the TextView. For example, I would like Talkback mode to announce "Log in - heading" rather than just "Log in".

What I have tried so far is adding this in my Activity's onCreate():

ViewCompat.setAccessibilityDelegate(v, new AccessibilityDelegateCompat() {
        @Override
        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
            super.onInitializeAccessibilityNodeInfo(host, info);
            info.setHeading(true);
        }
    });

In Talkback mode, there is no change - it still just announces "log in".

What I notice is that this method, onInitializeAccessibilityNodeInfo, is being called multiple times. When I step through in debugger, every time this method is triggered it shows that isHeading() is false, then set to true.

Am I using this method incorrectly? Why is it called many times? Why is info.setHeading(true) basically ignored?

How would I accomplish something similar, but with Talkback mode announcing "Label - Link" instead of header?

h_k
  • 1,674
  • 1
  • 24
  • 46

2 Answers2

4

Try this:

ViewCompat.setAccessibilityDelegate(v, new AccessibilityDelegateCompat() {
    @Override
    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
        super.onInitializeAccessibilityNodeInfo(host, info);
        info.setRoleDesccription("heading");
    }
});
JavaGhost
  • 406
  • 4
  • 8
  • Hi JavaGhost, I can do this many ways, but it is a bit of a "cheat". When navigating by heading, the OS still does not recognize this as a heading. After doing this, and selecting heading navigation mode, the text view is never focused. The effect is the same if I set the contentDescription on the TextView. When it's accessed normally, sure it says "heading", but it's not identified by the OS as a heading. – h_k Nov 11 '19 at 19:51
  • Ha Ha, don't call it as "cheat" but workarounds in cases where you want more control to change stuff dynamically. – JavaGhost Nov 18 '19 at 07:21
4

I have solved my issue!

The issue is that the TextView itself is not getting the focus. Instead, the container view, in this case the FrameLayout that wraps the TextView, was getting focus. That's why setting the TextView itself as a header was not appearing to work - the view around it was getting the focus.

So given the xml layout:

<FrameLayout
    android:id="@+id/fl_login_header"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:focusableInTouchMode="true" >
        ...
        <TextView
            android:id="@+id/tv_login_header"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/login_sign_in_to_your_account" />
        </FrameLayout>

There are two solutions:

API 28+:

<FrameLayout
    ...
    android:accessibilityHeading="true" >

or, in code, you can do the same thing as in my original question:

ViewCompat.setAccessibilityDelegate(v, new AccessibilityDelegateCompat() {
    @Override
    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
        super.onInitializeAccessibilityNodeInfo(host, info);
        info.setHeading(true);
    }
});

BUT you pass the container view in instead of the TextView.

h_k
  • 1,674
  • 1
  • 24
  • 46