Optimize your Android app UX for screen readers

Doug Stevenson
Mesmer
Published in
7 min readJun 9, 2020

In my last post, I discussed some ways to make sure your app’s design handles text with variable length and font sizes. This is a good starting point, however, for the legally blind, no increase in the size of text will help them read that text. Your design should also be accessible via a screen reader, such as TalkBack.

Android screen reader basics

For Android, Google provides two screen readers: TalkBack and Select to Speak. In order to see these options in the Accessibility settings, you should have the Android Accessibility Suite installed.

Android accessibility settings screen
Android accessibility settings screen

The primary reader is TalkBack. It provides both accessible navigation and text to speech. When enabled, it completely changes the way the touch screen works. A word of caution: if you enable TalkBack, you will want to go through the provided tutorial to understand how to get around. Without understanding navigation, you will likely get frustrated, as the touch screen will no longer work the way you expect. I have also found Google’s cheat sheets for TalkBack gestures and keyboard shortcuts to be very helpful.

On devices with Android 9.0 or later, there is a second screen reader called Select to Speak. This one is handy for preserving touch navigation while enabling quick access to screen reads. I recommend enabling this on the emulator or device you use for development and testing, as it will give you a good idea how your app is audibly rendered for those using TalkBack. It puts a small person icon in the bottom right corner of the screen in the navigation bar. Tap it, and it will pop up some controls that let you enable an entire screen read, or just touch a View whose content you want to hear.

Select to speak controls at the bottom of the screen
Select to speak controls at the bottom of the screen

What do images “say”?

One of the more important considerations is what to do when a screen reader encounters an image. Typically you use an ImageView in Android to display the image. This works fine for people with normal vision, but for the impaired, this image is possibly going to be useless. Android Studio will even warn you about this situation. If you’re an Android engineer, you’ve probably already seen this because of the way Android Studio warns you about missing contentDescription attributes in XML:

The full text of the lint warning here is:

Missing contentDescription property on image

Non-textual widgets like ImageViews and ImageButtons should use the contentDescription attribute to specify a textual description of the widget such that screen readers and other accessibility tools can adequately describe the user interface.

Note that elements in application screens that are purely decorative and do not provide any content or enable a user action should not have accessibility content descriptions. In this case, just suppress the lint warning with a tools:ignore=”ContentDescription” attribute.

Note that for text fields, you should not set both the hint and the contentDescription attributes since the hint will never be shown. Just set the hint. See http://developer.android.com/guide/topics/ui/accessibility/checklist.html#special-cases.

The right thing to do is assign the ImageView a value for contentDescription that describes the image, which will be read by screen readers when they encounter the view. This is similar to the way the alt attribute works for images in web browsers.

For decorative images without contextual meaning

Content descriptions are not desirable everywhere. Purely decorative images that do not have a meaning should have a value of @null to avoid speaking anything when the screen is read. However, the view is still discoverable by touch, and will render some dummy text, which is probably not what you actually want. To get an element completely out of the way of a screen reader, it should also have the importantForAccessibility attribute set:

android:importantForAccessibility="no"

Read more about the effective difference between contentDescription and importantForAccessibility.

Definitely think about what you want the aural experience to be for each image you place on screen, and mark it appropriately. This even includes TextViews!

TextView: What about truncated or ellipsized text?

Usually, for TextViews, there’s nothing you have to do to get a screen reader to correctly read the displayed text. By default, a screen reader will speak the entire text that you’ve placed into it using the text XML attribute or setText method. In many cases, this is good enough, but not always sufficient.

In my last post, I showed an example of using android:ellipsize="end" to automatically truncate long text so that it fits within the static vertical space for items in a menu:

If you’re concerned about what a screen reader will do with the ellipsized text as shown above, the good news is that screen readers will use exactly the text that you’ve set into the view, not just what appears on the screen. So, if the screen reader encounters a TextView, it will simply speak the entire contents of the text provided by the code. The screen reader is using the raw data in the view hierarchy, not the pixels on the screen, though it is using the position of each view on screen in order to determine the order they should be read. (In general, you can expect it to read views on the screen from left to right, top to bottom. If the order of text is important, you should test that before you publish the app, and change the order as needed.)

Do you really want to speak all of the hidden text?

Consider for a moment that a truncated TextView can hide a lot of extra text. Do you really want the screen reader to read all of it? If the text is very long, it might be too time-consuming for the user of your app to listen through it, given the context of what the screen wants them to accomplish. Visually, there might be no problem with truncated text, but aurally, it could be a UX disaster.

Remember that people using screen readers have a harder time skimming large amounts of text like your visually abled users. If this is a concern for your app, you could allow for a shortened version of the text to be used by screen readers. The shortened version could simply truncate the text to the first sentence of content ending with a period. However, note that this could be problematic, since a period has more meanings than simply ending a sentence.

A better solution is to allow for a completely new piece of metadata for the express purpose of being read aloud. This metadata can be customized for use with screen readers. It could also contain text that indicates that there is more to hear by adding the words “select for more” (assuming your app actually allows for that). App design and architecture that fully streamlines the experience of all of your users can be a worthwhile effort.

To change the way a TextView renders using a screen reader, you can use the contentDescription attribute, just like any other View. The screen reader will prefer the contentDescription text over the normal text. In fact, contentDescription works for all Android views, even custom views. (The general advice is not to use contentDescription with TextView, so be sure you are getting exactly the intended effect by adding it.)

ScrollView is also important for accessibility

In my last article, I pointed out that views that don’t render on screen are completely unusable and inaccessible to the user. The same is true for people using screen readers. If a view doesn’t occupy space on the screen for any reason (for example, it got pushed out of bounds by other content), it won’t be found and spoken by a screen reader. So, if you have content that doesn’t fit on screen for any reason, and you want the user to be able to see or hear its contents, you should put it in a scrolling container. Here’s a screenshot of content in a dialog that would be inaccessible without a scrolling container:

Screenshot of overflowing text in a ScrollView
Allow text to overflow and scroll with a ScrollView container, under all circumstances.

Abled users will, of course, be able to scroll through the content in a ScrollView using up and down scroll gestures as you would expect. Bear in mind that TalkBack users can not scroll in the same way. TalkBack provides its own gestures and keyboard shortcuts for navigating between the next and prior elements on screen. When the user navigates to a ScrollView, TalkBack will advance through its child views, automatically scrolling the screen as it goes. This style of navigation can make large amounts of content difficult to skip — there is no “fling” shortcut for TalkBack (though you can quickly move to the last item on the screen).

If you have large amounts of data to present, consider breaking it up into sections, initially hide the content of each section, then allow each section to be navigable by disclosure, similar to how Wikipedia’s mobile view works.

Screenshot of Wikipedia’s mobile view showing sections with disclosures
Wikipedia collapses sections under a heading with a disclosure arrow for faster navigation.

Great accessibility requires more than just enabling screen readers

Designing an app for accessibility goes beyond making sure all the text is readable through a screen reader. In order for an app to be a pleasure to use with accessibility tools, consider the actual user experience every step of the way.

--

--