Say I have a list of items, and one of the views in each item is a message, in a simple TextView, that is populated in code (dynamic data from a backend service).
<TextView
android:id="@+id/message"
style="@style/DefaultText"
/>
Visually it doesn't need a label; the list item layout is pretty clear. But listening to how TalkBack reads the screen, I think it would be beneficial to have a "label" or description for it. So that TalkBack would read something like:
Message: [the actual dynamic message content]
My question is: is it possible to add a label/description for a TextView that, firstly, does not replace the TextView content, but is read along with it, and secondly, only affects TalkBack (not the visual presentation)?
What I tried:
contentDescription
for the TextView. Doesn't work: if set, the actual content is not announced, only the contentDescription
. Hmm, maybe if I'd set this in code with the description prepended to the actual content... but is there no easier way?labelFor
pointing to @+id/message
. The problem is that it's also shown visually and screws up the design. If I make it not visible, one way or other, it seems TalkBack won't read it either. Alright, I found two solutions! As mentioned in the question, I'd rather have avoided doing it in code, but it seems for optimal results that's the way to go.
android:hint
in XMLThe most simple way is to set android:hint="Message"
for the TextView. TalkBack reads it after the actual text:
[the actual dynamic message content] Message
For my needs, with the message being optional, this has some drawbacks: the hint is announced even if the TextView has no actual content (I'd prefer to omit it then), and in that case it's also shown visually (not what I want). Also, I'd prefer TalkBack to read the hint before the actual text.
contentDescription
programmaticallyNot as simple, but not complicated either, and you have complete control over what TalkBack says.
In my case, preferring to omit the description if message is missing and having it read before the message content, I'd do something like this in the code that populates the list items:
textView.setText(message);
if (!TextUtils.isEmpty(message)) {
textView.setContentDescription(
context.getString(R.string.message_desc, message));
}
With resource:
<string name="message_desc">Message: %s</string>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With