engineering

January 28, 2020   |   9min read

Accessibility—Mistakes to Avoid When Implementing it in an Android App

Introduction

Nowadays, accessibility is a hot topic and a must-have of every well-designed and well-developed mobile application. Why? Because we want to reach a wider audience and create apps that can be used by everyone, including people with different types of disabilities. It is really challenging for them to use apps—especially for visually impaired people. We should give them all the best user experience. How can we make apps more accessible and easier to use by people with vision loss? Let’s answer this question.

Lately, in one of Polidea’s projects, I had an opportunity to implement accessibility in an Android app by adding TalkBack support. TalkBack is an app mostly pre-installed on Android devices, but it is also available for download in Google Play. In general, it is a screen reader—it gives the user spoken feedback when using an app, so it is not necessary to look at the screen. It helps visually impaired people to navigate through an app. With TalkBack on, navigation in an app is different than usual, and gestures vary (e.g. you scroll the screen not with one but two fingers).

While implementing accessibility, your main goal should be to make the navigation in your app as clear as possible for people with visual impairments. So your main question should be: how can I use opportunities that Android OS gives me to make my app more accessible, intuitive, and consistent with other Android apps?

Rules for accessibility in Android apps

To be honest, I was a little bit disappointed with my first experience of implementing accessibility. I have faced a lot of interesting issues and problems while trying to make my app work well with TalkBack, but I didn’t find many useful articles or examples to support me. That’s why I created a list of rules that can help you with your doubts and show you how you can avoid mistakes. In my opinion, they are essential and should be there any time you implement accessibility, not only in an Android app. Let’s dive into it.

Provide easy and intuitive access to all UI elements

Remember one crucial thing—TalkBack cannot focus on elements hidden from the screen. For example, when an app has a list of elements, and you can swipe each of them to discover hidden options. TalkBack can’t focus on these hidden options before you swipe the element.

text

This often happens in email apps—by swiping an email, icons with “delete” or “archive” actions are displayed on UI. It is almost impossible for visually impaired users to discover these options because with TalkBack on, you have to know where to swipe, and you must swipe this particular element with two fingers. What can be done about it?

This situation requires a different way of access to those hidden icons. One option is to display the context menu on the element that can’t be swiped with one finger. All we have is to use the addAccessibilityAction() method on ViewCompat class and pass the view, which can’t be swiped as a first argument and action label as a second argument. This context menu is displayed after “swiping up then right” action. The same actions that can be performed by clicking hidden elements can be listed on this menu. A smart, easy, and clear solution!

ViewCompat.addAccessibilityAction(holder.itemView, "Delete") { _, _ ->
       delete()
       true
        }

text

Screenshot from an example app

In the picture above, you can see an example context menu. It doesn’t look very nice, but it doesn’t have to, because the most important thing is providing intuitive access to hidden icons for visually impaired people.

Every element should have a descriptive label that TalkBack can read

It is quite an obvious rule, but always be aware of providing descriptive labels to anything important for a user. In Android, adding a label to an element is possible by setting a value to the android:contentDescription attribute. Content description for TextView is set by default to the same value that is set to android:text attribute. And this can be tricky! Imagine that you use an app with TalkBack on, and you hear a number. Just a number. You don’t know what it is exactly, it can be anything, like a date of birth, date of an event, or today’s date.

Without a meaningful explanation, the user can get confused, and our application can be hard to use. We should always remember to change the default label when it is not descriptive enough by providing additional information about the element.

Don’t let TalkBack focus on hidden elements

I remember one strange situation when I started implementing accessibility. I noticed that TalkBack was focusing on elements from the previous screen. That was strange because I knew that focus can be set only on visible elements. The problem was evident, and it was almost impossible to use my app—the behavior of TalkBack’s focus was too unpredictable. Luckily, the solution was quite simple.

This situation is common in single-activity and multiple fragments apps. When the user clicks on a button, and another screen is shown. Behind the scenes, it means that the subsequent fragment is added to the back stack. It happens by invoking one of the methods in the FragmentManager class. It can be the replace() method—when the previous fragment is replaced with the next fragment or the add() method—when the previous fragment stays on the back stack, and the next fragment is on top of it. When a fragment is added instead of being replaced, the elements from the previous fragment are not visible on the screen, but TalkBack can still focus on them.

As developers, we can manage it in one simple way. When we detect that the back stack is changed, we can find the last added fragment, and we can make this fragment’s root view important for accessibility. We can do this by setting the flag View.IMPORTANT_FOR_ACCESSIBILITY_YES on this view. Then, all the remaining fragments and their elements will be not important for accessibility when you set the flag View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS on them. Additionally, with the magic of Kotlin, we can wrap this all in the extension function on FragmentManager class and call this function in the OnCreate method in our activity and base fragment.

fun FragmentManager.setupForAccessibility() {
    addOnBackStackChangedListener {
        val lastFragmentWithView = fragments.lastOrNull { it.view != null }
        for (fragment in fragments) {
            if (fragment == lastFragmentWithView) {
                fragment.view?.importantForAccessibility =
                        View.IMPORTANT_FOR_ACCESSIBILITY_YES
            } else {
                fragment.view?.importantForAccessibility =
                        View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
            }
        }
    }
}

Sometimes less means more

Without a doubt, users should know the result of the action which they perform. So, when, for example, they click on a button, they expect a particular action to be invoked. By default, when a button is focused, TalkBack will communicate: “Double tap to activate.” This isn’t very descriptive, is it? Don’t worry, we can add some improvements.

In Android, it is possible to add usage hints on clickable elements by using AccessibilityDelegate class. In this class, we can override the onInitializeAccessibilityNodeInfo() method and add additional metadata about the view to the AccessibilityNodeInfo object. This metadata can be a label of a specific action that the user should perform by clicking on a button. In practice, we can change the mentioned “Double tap to activate” to, for instance, “Double tap and hold to watch a video.”

fun View.doOnInitializeAccessibilityNodeInfo(block: (info: AccessibilityNodeInfoCompat?) -> Unit) {
    ViewCompat.setAccessibilityDelegate(this, object : AccessibilityDelegateCompat() {
        override fun onInitializeAccessibilityNodeInfo(host: View?, info: AccessibilityNodeInfoCompat?) {
            super.onInitializeAccessibilityNodeInfo(host, info)
            block(info)
        }
    })
}
private fun setAccessibilityAction() {
        button.doOnInitializeAccessibilityNodeInfo { info ->
            info?.addAction(AccessibilityNodeInfoCompat.
                    AccessibilityActionCompat(AccessibilityNodeInfoCompat.ACTION_CLICK,
                    "Watch a movie"))
        }
    }

Awesome! It is a great option to add some improvements. But… is it effective in every case? Imagine this label and usage hint on a button: “Main app settings. Button. Double tap to enter the main app settings.” Too much content can make the user even more confused and overwhelmed because of this huge wall of text read by TalkBack. We should keep our app readable and clean. If the button’s label is descriptive enough, adding a usage hint should be avoided. The main cause of it is that it takes more time for the users to listen to it, and, in their perspective, it can be annoying.

Work closely with UX designers

Taking advantage of the designers’ experience is one of the best things that can support you in implementing accessibility well. I had a few discussions with very talented and experienced people, and they helped me a lot! More than reading articles or documentation. It is even more valuable, especially when designers had the opportunity to work with accessible UI or talk with visually impaired people about their experience with using TalkBack. It is always great to share your thoughts and doubts with designers as well as other team members—it will for sure help you keep an app more intuitive for the users and keep views behavior more consistent with other Android apps. Special thanks to the amazing team: Utilo designers for their invaluable help with my doubts. Teamwork is key to success!

text

Most of all—be empathic

In my opinion, this is the most important rule of all. In general, it means that it’s sometimes good to close your eyes and put TalkBack on—and experience the app like a visually impaired person. Just try to put yourself in somebody else’s shoes! I know that it can be hard for the first time, even when you try it with an app that you know very well. Believe me, I was so confused with a lot of information that TalkBack was giving me—notifications, announcements, looong usage hints. Really, I just wanted to turn TalkBack off, or at least speed it up. And, in the end, I learned one crucial thing: while implementing accessibility, an overcomplicated app can be a nightmare!

Sometimes, we forget that things are different from the developer’s point of view and the user’s. Developers will create such beautiful, clean code, and they will be proud of their work. But later, they run the app to see how it works. Then, the level of their satisfaction decreases dramatically. And YES, I was also in this exact situation. I removed huge chunks of code because there was too much information for the user, and it was useless. When implementing accessibility, keep the user experience clean.

Speaking of clean…

This is not the end! There is one tool I could really recommend to you for implementing and testing accessibility or even creating a design. It is called Accessibility Scanner. This is one of my favorite accessibility boosters. It is an app that is available on Google Play. And the best thing about it? You don’t have to be a developer to take advantage of it. With this great tool, you can scan every screen in your app to investigate if there is a way to improve accessibility. It can give you useful hints and suggestions, e.g., about adding “contentDescription” attribute to the views, changing contrast or size of icons’ tappable area. Things that could be missed while writing code will never be missed again.

As we finish discussing the do’s and don’ts, let me leave you with this final thought.

Conclusion

To sum up, it is not easy to implement accessibility well—because sometimes it is hard to say what it really means. It is not just about the theory. Reading documentation is an important thing, but so is your empathy, discussing possible options with the team, your developer intuition, and much more. Keep TalkBack’s navigation in your app as simple as possible and consistent with other Android applications. Create clean instructions for visually impaired users, taking into account the blind persons and those who have other visual difficulties. They also have to be supported by TalkBack sometimes. Make sure it’s not misleading for them.

Patrycja Sosnowska

Junior Software Engineer

Did you enjoy the read?

If you have any questions, don’t hesitate to ask!