VRT Sauce

As you can already tell there are lots of great APIs and tools available for developers and the Android ecosystem is becoming increasingly more friendly for accessibility users.

What’s more is that when you stick to default implementations of the Android framework you will already have a minimum of accessibility features enabled in your app.

So what does VRT do extra on top to provide an even better experience?

I tried ordering them according to their importance.

With the tips on the bottom being the ones with lower priority.

Content descriptions

Make sure that every view that a user can touch has a correct label.

This will ensure that it gets picked up correctly by the screen reader.

If it is a static view you can do this in XML or programmatically.

# XML

<TextView

android:contentDescription="@string/your_accessibility_text"

android:layout_width="wrap_content"

android:layout_height="wrap_content" /> # Kotlin val itemView: View = layout.find(R.id.someView)

itemView.contentDescription = "Your accessibility Text"

If a view is not of interest for an accessibility user, think of little icons, you can ignore the view by using:

<ImageView

android:id="@+id/some_unimportant_icon"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:importantForAccessibility="no"/>

To alleviate the problem of generating a fitting accessibility text for both Android and iOS clients we fetch our accessibility text straight from our backend.

[

{

"id": "1533565019306",

"title": "Twee doden en tientallen gewonden",

"accessibilityText": "Buitenland, Twee doden en tientallen gewonden bij de explosie van een tankwagen in Bologna, aangepast ${time}, dit artikel bevat video"

}

] "accessibilityText": "Buitenland, Twee doden en tientallen gewonden bij de explosie van een tankwagen in Bologna, aangepast ${time}, dit artikel bevat video"

}

]

The only computing that needs to be done by the client is replacing the ${time} with the correct time according to some business logic and place it on the itemView.

To make sure you don’t forget this we have a base layout interface which enforces you to have an accessibility text.

You could even make a default interface, but we rather wanted it to be explicit about it.

Grouping of views

When you are composing views together it makes sense to have but one content description for one block instead of each individual item.

The reason behind this is because screen readers like Talkback will otherwise read every little view separately. Grouping views together combines the accessibility text.

In the screenshot below we grouped all views in a list item as one accessibility group with a content description

The way Google recommends you to do this is by placing an android:focusable on to your parent ViewGroup however that breaks tab navigation as explained in this Github issue.

We choose to place android:importantForAccessibility="no" on each view that should be ignored by the screen reader and instead only provide a content description for the parent view.

This will also ensure that the gesture for going to the previous/next item (swipe left/right) is properly implemented

If you want more fine-grained control over what view should be selected next you can take a look at:

android:nextFocusLeft="@id/view_selected_when_swipe_left"

android:nextFocusRight="@id/view_selected_when_swipe_right"

Text Scaling

In a previous section, we talked about how a user can enlarge text displayed on the screen. The only downside to this is that you should declare your font sizes in SP rather than in DP’s

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textSize="14sp" />

Even better would be to look at the auto sizing TextView it allows for an automatically scaling TextView widget that will fill all available space.

Thanks to Jetpack it is backported all the way back to Android 14.

State & Correct Intent

As a user is it important to know which page or which item is currently active.

Again by leveraging default views this behavior is done for you, but in situations where that is not the case, don’t forget to include it.

Default behavior of a TabLayout will tell you which tab is currently active

Custom Views

You might have custom views in your project fetching periodical results and showing new items in a colorful manner.

Consider notifying your visually impaired end user by using:

view.announceForAccessibility("New items were being fetched")

This will interrupt the screen reader and will broadcast the defined string.

Maybe your custom view is difficult to use or it has a dense set of buttons which would be annoying for people with dexterity impairments.

You could take a look at AccessibilityDelegateCompat this class allows you to define a custom view only for Accessibility users.

Detect Accessibility On

In some situation we are even changing the behavior of the app depending on when accessibility is enabled or not.

Think about running expensive beautiful animations.

Why would you want those if you can detect a user is using a screen reader.

We use a little utility class for this.

Conclusion

If you have come this far I hope that you were inspired to make your apps more accessible. As you can tell it is a rather low effort to fulfil and yet it means a lot to millions of users.

Got any questions? Leave them below.

Special thanks to AnySurfer and Marc Walraven.