-1

I'm using a custom dynamic contentDescription for my textview, so it has been implemented in my java class and not in my xml file.

private void enableButton(TextView textView, boolean enabled) {
    if (textView == null) {
        return;
    }
        if (!enabled) {
            textView.setContentDescription(textView.getResources().getString(R.string.install_disabled));
        } else {
            textView.setContentDescription(textView.getResources().getString(R.string.install));
        }
    textView.setEnabled(enabled);
}

After I'm enabling my textview to be clickable, and when talkback is enabled, focusing on my textview is announcing the state of my textview which is "disabled". Is there a way to not announce that state?

I do not want to set the accessibility to be not important because I still want my dynamic contentDescription to be recited when talkback users focus on the textview.

Suggestion: I believe the culprit is the "setEnabled" method that is somehow triggering and announcing the state of the textview, but I'm still not able to stop it from reciting that last.

Red M
  • 2,609
  • 3
  • 30
  • 50

2 Answers2

0

My first answer is: LEAVE IT ALONE! The "disabled" announcement tells a TalkBack user that there is a user interface control there, that under some circumstances can be interacted with, but is not currently active. Given your description, this is exactly what you have. To remove the announcement is actually going to make things WORSE from an accessibility perspective, the explanations for why this is the case are covered in WCAG 1.3.1.

Definitions:

Button = android.widget.Button

button = a user interface component that does something when you click it.

Text = a user interface component that conveys information, but is not active

Long story short, the fact that the control is ever in a state that it can be active and "not disabled" is significant information on its own, and SHOULD be shared with the user. ESPECIALLY since you're using a "TextView" to implement this. This isn't a super uncommon practice, but one of the ways TalkBack calculates roles (button, link, image, text, etc) is by looking at the Class/Type of object. So, when it sees a TextView, it is going to assume Text, unless you inform it otherwise. Now, since you have added click listeners to your TextView (or Gesture Recognizers, or whatever) TalkBack may be able to figure out that the thing you're dealing with is actually a "button", and it may not. REGARDLESS, the fact that this "button" (lower case B!) is not active is important state to share with the user, and communicates to them the fact that they can somehow enable it and come back and interact with it later. This is immensely important information! Imagine if every button/link on a WebPage looked exactly like plane text? How would you know what to interact with?

Now, I will show you the different pieces of this puzzle, as information, but I really do encourage you to leave the announcement alone. This is coming from someone who routinely speaks at Accessibility conferences on Native Android development, PLEASE LEAVE THIS ANNOUNCEMENT IN. To not do so shows a misunderstanding of how users with sight impairments want to perceive controls within your application, and the information that is important to them.

The setEnabled() function on a TextView corresponds directly with the isEnabled() property of AccessibilityNodeInfo.

In order to implement the behavior you want, you want the AccessibilityNodeInfo representation of your TextView to be different from that of the actual representation of your TextView. In order to do this you can use AccessibilityDelegate, I'm actually not sure which callback you want to use. In one of these the node is likely to be "sealed" and in one of them it might not be sealed yet. You obviously want the one where the node is not yet sealed! Regardless the general approach is:

textView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
    @Override
    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {

        // Let the default implementation populate the info.
        super.onInitializeAccessibilityNodeInfo(host, info);

        // Override this particular property
        info.setEnabled(whateverYouThinkItShouldBe);
    }
});
MobA11y
  • 18,425
  • 3
  • 49
  • 76
  • disabling the textview is not only applied to talkback users, it's also applied to non talkback users. It's part of the app functionality. My team and I decided to use textview instead of a button because it's much more customizable compared to button from a material design perspective, but that's another story. The functionality itself is working fine. The bummer is when announcing the state "disabled" it's totally misleading to talkback users. I introduced a contentDescription that makes much more sense, but the textview class is appending "disabled" at the end of my contentDescription. – Red M May 23 '17 at 16:08
  • Are you a politician? You really like giving vague answers. This is a software development site. You need to be precise. Note, that I clearly understand the relationship between TalkBack and NON TalkBack users, as the first question was specifically directed at NON TalkBack users, you just decided not to read/comprehend it properly. So I ask again. "What puropose is "disabling" the TextView serving for NON TalkBack users?" For example: Disabling a Button typically means that it is present in the UI, but the normal action associated with it does not get performed when a user "clicks" it. – MobA11y May 23 '17 at 17:44
  • It may even change colors from like a Dark Blue, to a Light Grey, to let a user know that it is not active at the moment. That is the level of detail I need to give you an answer to this question. What is it that a perfectly capable user experiences when your TextView transitions from "enabled" to "disabled". – MobA11y May 23 '17 at 17:47
  • Lol, I thought I was in a CNN political debate. I'm not dodging your questions or anything like that, I'm seeking help that's it. Okay, so the purpose of disabling textview is that the user won't be able to click it just like you explained for Button. So the functionality is: I have a list of card items in a recyclerView, and if non of these items is selected, the textview is not clickable but is UI present. Hope that helps. – Red M May 23 '17 at 18:50
  • Beautiful, that is exactly the answer I needed! Updating the answer. – MobA11y May 23 '17 at 19:18
  • @ChrisCM I am looking for a way to add to the output, example: "some label, button, disabled, [hint as to why]" Any idea if / how that can be achieved ? – Tyler Turnbull Apr 30 '20 at 15:44
  • This is a new question. – MobA11y Apr 30 '20 at 15:46
0

Use setClickable(false) to replace setEnabled(false) will solve this problem.