9

I have an EditText like below

<EditText
    android:id="@+id/extUsername"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:contentDescription="Username field"
    android:hint="Username" />

I want TalkBack to say "Username field" but it says "Username". It ignores contentDescription.

Do not tell me to remove hint or contentDescription. I need to use both.

Any advices will be appreciated.

Egemen Hamutçu
  • 1,602
  • 3
  • 22
  • 34
  • 7
    Don't set content descriptions on edit fields. Don't include component type in content descriptions. The accessibility service handles this, if needed. Just set the `android:hint` or use `android:labelFor` if you have a separate label. – alanv Apr 27 '15 at 19:44

6 Answers6

10

What you want to do is use LabelFor instead. LabelFor allows a visual label to be associated with an EditText box. You can make the visual label invisible if you'd like, so that it doesn't change your visual layout.

The down side to hints, is that they disappear after text is entered, making them pretty poor accessibility tools. If you're relying on hints for your Accessibility information, your app is not accessible.

Do something like this:

<TextView
     android:text="@string/yourEditTextDescription"
     android:labelFor="@+id/editTextField" />

<EditText android:id="@+id/editTextField"/>
MobA11y
  • 18,425
  • 3
  • 49
  • 76
  • I got the error in xml file. TextView needs android:layout_width and android_height error message shown. How can i handle it. – arvind grey Oct 12 '17 at 12:40
  • 4
    Add android:layout_width and android:layout_height? I removed scaffolding to demo just the important bits for accessibility. Your xml still needs to include all of those other styling bits that Android usually expects. – MobA11y Oct 12 '17 at 13:40
  • I tried with all the styling bits usually we use in the xml file. But i got the error mesage castException: android.widget.TextView cannot be cast to android.widget.EditText – arvind grey Oct 12 '17 at 13:53
  • It sounds like your trying to cast a TextView to an EditText... You should add your Java and your xml to a different question. Your current problem is unrelated to this. And extended debugging conversations in comments are bad. – MobA11y Oct 12 '17 at 14:03
  • It seems that if you make the `TextView`'s visibility either `invisible` or `gone`, TalkBack doesn't read this label when you tap on the `EditText`. – Carmen Oct 30 '19 at 11:10
  • They probably made a change. This was valid in 2015... Android has come a ways since then :). I would recommend a similar solution today, but doing so with AccessibilityDelegates. – MobA11y Nov 15 '19 at 15:21
2

According to the official documentation, you shouldn't be setting android:contentDescription equal to anything. Instead, only use android:hint.

<EditText
    android:id="@+id/extUsername"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:hint="Username" />

"field" from your contentDescription should be removed, because TalkBack will announce it as "Username edit box"

Shalbert
  • 1,044
  • 11
  • 17
0

Unfortunately, android:hint will always override android:contentDescription. You can create TextView which you will use only to set android:labelFor but from my experience TalkBack will then read both hint and labelFor.

The right way to add TextView which is only for labeling EditText for TalkBack :

    <TextView
         android:layout_width="0dp"
         android:layout_height="0dp"
         android:text="@string/yourDescription"
         android:labelFor="@+id/editText" />

    <EditText android:id="@+id/editText"/>

So one of the solutions is that you can check to see if TalkBack is on and change hint programmatically. You can check if TalkBack is on with:

  if(context.isScreenReaderOn){
    ...
}

And you create an inline function in Kotlin like :

fun Context.isScreenReaderOn():Boolean{
    val am = getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    if (am != null && am.isEnabled) {
        val serviceInfoList =
            am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN)
        if (!serviceInfoList.isEmpty())
            return true
    }
    return false}
-1

Note: For EditText fields, provide an android:hint attribute instead of a content description, to help users understand what content is expected when the text field is empty. When the field is filled, TalkBack reads the entered content from content description to help user, instead of the hint text.

For Hint -> android:hint

For TalkBack -> android:contentdescription

Chetan Joshi
  • 5,582
  • 4
  • 30
  • 43
  • Hints should not contain important information, like the name of the field. Username is very important information, and should be more than temporary. A TalkBack user shouldn't have to delete their entered text, to know what it is they entered the text for. A bad hint: Username. A good hint: John.Smith. – MobA11y Oct 12 '17 at 13:37
-2

You should extend EditText class with overriden TextView.getTextForAccessibility() method to get expected behaviour in the following way:

public CharSequence getTextForAccessibility() {
    CharSequence text = getText();
    if (TextUtils.isEmpty(text)) {
        text = getContentDescription();
    }
    return text;
}
Dmitry Ko
  • 25
  • 4
  • 1
    This method appears in TextView's source code, but is not reported here https://developer.android.com/reference/android/widget/TextView.html and I cannot override it. – manfcas Jun 03 '16 at 16:24
  • That's a private method, you can't override it. – Niall Aug 01 '18 at 11:17
-8

You need to add it in your string.xml file:

<string name="description">your desc goes here</string>
Hems
  • 1
  • 8