Android Accessibility by Tutorials-Razeware LLC. (2022)
Android Accessibility by Tutorials-Razeware LLC. (2022)
Notice of Rights
All rights reserved. No part of this book or corresponding materials (such as text,
images, or source code) may be reproduced or distributed by any means without
prior written permission of the copyright owner.
Notice of Liability
This book and all corresponding materials (such as source code) are provided on an
“as is” basis, without warranty of any kind, express of implied, including but not
limited to the warranties of merchantability, fitness for a particular purpose, and
noninfringement. In no event shall the authors or copyright holders be liable for any
claim, damages or other liability, whether in action of contract, tort or otherwise,
arising from, out of or in connection with the software or the use of other dealing in
the software.
Trademarks
All trademarks and registered trademarks appearing in this book are the property of
their own respective owners.
raywenderlich.com 2
Android Accessibility by Tutorials
raywenderlich.com 3
Android Accessibility by Tutorials
raywenderlich.com 4
Android Accessibility by Tutorials
raywenderlich.com 5
Android Accessibility by Tutorials
raywenderlich.com 6
Android Accessibility by Tutorials
raywenderlich.com 7
L Book License
• You are allowed to use and/or modify the source code in Android Accessibility by
Tutorials in as many apps as you want, with no attribution required.
• You are allowed to use and/or modify all art, images and designs that are included
in Android Accessibility by Tutorials in as many apps as you want, but must include
this attribution line somewhere inside your app: “Artwork/images/designs: from
Android Accessibility by Tutorials, available at www.raywenderlich.com”.
• The source code included in Android Accessibility by Tutorials is for your personal
use only. You are NOT allowed to distribute or sell the source code in Android
Accessibility by Tutorials without prior authorization.
• This book is for your personal use only. You are NOT allowed to reproduce or
transmit any part of this book by any means, electronic or mechanical, including
photocopying, recording, etc. without previous authorization. You may not sell
digital versions of this book or distribute them to friends, coworkers or students
without prior authorization. They need to purchase their own copies.
All materials provided with this book are provided on an “as is” basis, without
warranty of any kind, express or implied, including but not limited to the warranties
of merchantability, fitness for a particular purpose and noninfringement. In no event
shall the authors or copyright holders be liable for any claim, damages or other
liability, whether in an action of contract, tort or otherwise, arising from, out of or in
connection with the software or the use or other dealings in the software.
All trademarks and registered trademarks appearing in this guide are the properties
of their respective owners.
raywenderlich.com 8
Before You Begin
This section tells you a few things you need to know before you get started, such as
what you’ll need for hardware and software, where to find the project files for this
book, and more.
raywenderlich.com 9
i What You Need
• Kotlin 1.6 or later: This book uses Kotlin 1.6 throughout. The examples may work
with an earlier version of Kotlin, but they are untested.
If you haven’t installed the latest version of Android Studio, be sure to do that before
continuing with the book. The code covered in this book depends on Android 12,
Kotlin 1.6 and Android Studio Chipmunk — you may get lost if you try to work with
an older version.
raywenderlich.com 10
ii Book Source Code &
Forums
• https://github.com/raywenderlich/acca-materials/tree/editions/2.0
Forums
We’ve also set up an official forum for the book at https://
forums.raywenderlich.com/c/books/android-accessibility-by-tutorials. This is a great
place to ask questions about the book or to submit any errors you may find.
raywenderlich.com 11
”It’s the support of many people that made this book possible.
My computer science professors first showed me what I could
do to help people through software. My peers supported me as
I learned more about tech, accessibility, and writing. The
editing team on this book has been incredible in building this
together. Finally, I couldn’t have done this without the
support of my husband, Tyler, encouraging me every step of
the way. Thank you, all.”
— Victoria Gonda
raywenderlich.com 12
Android Accessibility by Tutorials About the Team
raywenderlich.com 13
Android Accessibility by Tutorials About the Team
raywenderlich.com 14
Section I: Android
Accessibility by Tutorials
Begin your journey into learning about building, testing and customizing accessible
apps on Android using WCAG through hands-on, step-by-step tutorials.
raywenderlich.com 15
1 Chapter 1: Why
Accessibility
By Victoria Gonda
Thank you! By picking up this book, you’re proving that you care about an important
topic: accessibility, which is often shortened to a11y. Whether you’re looking to
deepen your existing accessibility knowledge, or are beginning your learning
journey, this book will support your goals.
In this first chapter, you’ll discover what accessibility is and answer the question:
Why should I care about accessibility? Once you reach the end of this chapter, you’ll
have several answers to that question, and you’ll be able to have effective
conversations with your peers about why developers should prioritize accessibility in
their designs.
And now you’re hungry. You’ve got an insatiable craving for a burrito, and you decide
to try a burrito-ordering app a friend recommended. As your hunger grows, so does
your frustration. You can’t place an order because your broken hand is making it
difficult to use your phone. Additionally, you don’t know which buttons do what.
Something is missing from the form, but the app doesn’t say what. You desperately
need some guacamole on this burrito, and you can see the “add guacamole” option
but can’t select it.
raywenderlich.com 16
Android Accessibility by Tutorials Chapter 1: Why Accessibility
How would you feel? A little hangry? Is it your right to order that burrito? What’s
your perception of this food delivery app?
An accessible app means that most people can use it without help from another
person, regardless of ability or situation. When there’s a mismatch between the app
and the users’ abilities, an app is considered inaccessible.
Inaccessible apps put barriers between a user and the task they are trying to
do.
You can see ways physical objects are accessible, be it ramps in front of buildings or
braille on the elevator buttons. But what does accessibility mean for digital objects,
specifically, your apps? And why should you care?
This chapter focuses on that second question, and the rest of the book is dedicated to
the first.
There are many reasons to care, including those below—in no particular order. By
developing an accessible app you:
• Drive innovation.
raywenderlich.com 17
Android Accessibility by Tutorials Chapter 1: Why Accessibility
Note: Does that number surprise you? Keep in mind two points:
1. Many people have invisible disabilities. You could know someone your
whole life and never know they have dyslexia and struggle to read. The young
mom you walk past in the grocery store may have a perfect, happy-go-lucky
face but you don’t know that she’s in chronic pain from a disease that destroys
her ligaments and muscles.
raywenderlich.com 18
Android Accessibility by Tutorials Chapter 1: Why Accessibility
Avoiding Assumptions
As a developer, it’s a force of habit to assume what people will and won’t do with
your app. Maybe you think: “I’m building a fitness app. People with motor
disabilities aren’t using my app” or “I have a parking app. Why would anybody with
vision impairment think to use it?”
You should not make assumptions about what people can do or the value they get
from your app. Every single person has their own story and way of interacting with
the world.
Maybe that user with vision impairments books parking spaces for a friend, who’s
coming to visit soon. Or that user with motor impairments is helping their cousin
train for a triathlon with your fitness app.
There are a million possibilities. You can’t assume you know them all. In addition,
you can’t assume that everyone who has a disability with the same name has the
same abilities. Disabilities manifest themselves in diverse ways with different
people.
If you think that two people with hearing disabilities will experience your app the
same way, you’ll be wrong.
Because of laws such as the Americans with Disabilities Act (or ADA) in the United
States and the Web Accessibility Directive (or WAD) in the European Union, it’s
prohibited to discriminate based on disabilities.
Here’s a powerful example of why you should care about accessibility: Guillermo
Robles wanted to order from Domino’s Pizza. More than once, Robles used the
Domino’s Pizza app to place an order only to discover he could not.
See, Robles is blind and uses assistive technologies, but the app did not support the
correct technologies. He brought his concerns to court and won in the case Robles v.
Domino’s Pizza (https://law.justia.com/cases/federal/appellate-courts/
ca9/17-55504/17-55504-2019-01-15.html).
raywenderlich.com 19
Android Accessibility by Tutorials Chapter 1: Why Accessibility
Back to your app: Someone can sue you for creating an inaccessible app if you
market your app in any country that has these protections if you don’t follow
accessibility guidelines. That sounds scary—and expensive!
It’s a good thing that you’ll learn about those guidelines in this book so you can
avoid that. Surely, Domino’s wishes it had your foresight.
Have these functions caused you to enjoy the apps on your device more than you
might have otherwise? All these actions are supported by accessibility features.
Stop and think: What everyday features do you use, either in the physical or
digital world, that could be an accessibility feature? Hint: Many things have
multiple ways to consume information or perform a task, which improves their
accessibility.
Supporting accessible features makes for a more enjoyable experience for all of your
users. Not only does it manifest itself in the ways described above, but it also makes
your app more consistent and easier to use, which increases users’ happiness and
engagement.
raywenderlich.com 20
Android Accessibility by Tutorials Chapter 1: Why Accessibility
For example, when you integrate with the device system in a way that makes your
app accessible, it means that if you port your app to a TV platform, you’ll be able to
navigate it with a remote. In the case where you enable your app for Android Auto,
the app can be used via voice. When users attach a keyboard to their tablet, they’ll be
able to navigate that form you have in your app using the keyboard. Who really wants
to move the mouse or tap the screen to move to the next field when you can press
tab?
Driving Innovation
Designing with accessibility in mind encourages you to make a better product and
can drive innovation. Scholars have studied and discovered that by placing limits on
a project, you foster greater creativity. After all, an app that does EVERYTHING is a
poorly designed product.
So, maybe you can’t fit everything you want onto a certain screen because the view
needs to be large enough to interact with and consume. This means you need to get
creative and really think about what content you need where.
You get to come up with fresh new ways to communicate to your users what you
mean, and you are required to think hard about how to make your app simple and
easy to use.
These constraints may feel like a burdensome creative writing assignment, but the
limitations will improve your creative processes when you design apps!
Stop and think: Pick a screen in one of your favorite apps. Now pick a
constraint and think about how you might change the screen. Maybe the
constraint is that you can only have half the content on the screen, or that
everything needs to be 2x bigger. Some other options might be you can only
use black and white, or there are no images allowed.
raywenderlich.com 21
Android Accessibility by Tutorials Chapter 1: Why Accessibility
Because you’re doing the same thing multiple places in the app, you, as the “lazy
developer” will find a way to do it once and abstract it away. And surely, your
designers will welcome an established design system.
This is great news for you too! You’ll have plug-and-play components that allow you
to build new features at lightning speed. The gains you would have made by ignoring
accessibility may help you in the short term, but supporting accessibility will help
you in the long term.
While maintaining an accessible app, you’ll also find that it encourages and supports
conducting UI tests in your app. Espresso tests on Android even hook into
accessibility services and Jetpack Compose tests use the same nodes that
accessibility services get information from! You’ll learn more soon about how UI
tests support your quest for a more accessible app.
One of the biggest themes you’ll learn in this book, on top of how to make your
Android app accessible, is how designing with accessibility in mind can improve your
product and engineering practices, justifying your upfront investment.
Right here, right now is your chance to change your thinking from “We don’t have
the resources to think about accessibility” to “We don’t have the resources to NOT
think about accessibility.”
There were hints that neglecting accessibility can cause you to lose money above.
For example, by supporting accessibility in your apps, you’re minimizing the risk of
incurring legal fees and liability due to non-compliance.
You’ve already read that having an accessible app makes for a better product.
Following the guidelines makes it possible for people with disabilities to use your
app and enables more users to have better experiences with your app. When your
app delights people, they’re more likely to rate it highly and tell their friends about
it.
Imagine a person named Tyler downloads the trial version and then discovers he
can’t use your app. That’s one less paying customer.
raywenderlich.com 22
Android Accessibility by Tutorials Chapter 1: Why Accessibility
But wait — it’s not only him. You’re also losing every single referral he would have
given if he had a better experience. You lose the people who see his one-star review
and decide not to download your app.
Then, those people who decided not to use your app, never get to refer their friends
to it. This branching can grow exponentially.
What about the people who can use your app? Imagine someone named Laura, for
example, who isn’t disabled but struggles to remember how to use apps. They use
your app but feel discontent with it.
They might continue to use it but will not recommend it to others. They are already
trying out competitors’ apps to find one that gives them a better experience and has
complained about your app to their friends.
Society has normalized accessibility in the physical world with affordances like
dedicated parking spaces and wheelchair-accessible layouts in grocery stores. Now
that so many companies exist online, the tech sector needs to consider accessible
user experiences as a key requirement for all user experiences.
When you market an inaccessible app, you send the message to some people that
“We don’t want you here”. You may not realize you’re acting in a hurtful way, but
that doesn’t mean that your insensitivity doesn’t hurt.
raywenderlich.com 23
Android Accessibility by Tutorials Chapter 1: Why Accessibility
-Haben Girma
In the end, you should build quality apps because you care about having a quality
app that can reach the biggest audience possible. And build accessible apps that
demonstrate the care that you want to see in the world.
You now understand why you should care about making your app accessible to
everyone, regardless of how they perceive or operate it. To help you wrap your head
around what that might look like, you need to know about some of the different
situations that cause people to experience your app differently.
Someone might struggle to see what’s on-screen because they have color-blindness
or because it’s bright outside. They might have a hard time performing a gesture
because they have tremors or because they broke their hand. They might not hear
the content of your video due to hearing loss or because they are in a noisy place.
These people often use assistive technologies to allow them to consume your app in
a way that makes sense for them.
Accessible design improves your app for so many people in all kinds of situations.
There are four different categories where the user’s ability can change the way they
experience your app:
1. Visual.
2. Motor.
3. Auditory.
4. Neurodiversity.
raywenderlich.com 24
Android Accessibility by Tutorials Chapter 1: Why Accessibility
Visual Impairments
There is a wide range of ways people might experience visual limitations, from being
near-sighted or having color blindness, to being legally blind. Other visual
impairments include:
• Tunnel vision.
• Wooly or cottony opacity in the central vision but not necessarily the peripheral
vision.
• Cloudy vision.
• Light sensitivity.
• Double vision.
This grid shows a simulation of different vision impairments. These were generated using
the NoCoffee Chrome plugin. Search 'Vision Simulator Chrome plugin' to try it yourself.
raywenderlich.com 25
Android Accessibility by Tutorials Chapter 1: Why Accessibility
Many of these have ranges in themselves, for example, low vision loss to complete
vision loss. Vision loss could be in one or both eyes. It could be temporary, such as
after an injury or after the eye doctor dilates your eyes.
When building apps, you should not make assumptions about what users can and
cannot see, as each user’s visual experience will be unique. You should also keep in
mind that people might be using assistive technologies such as magnification or
screen readers.
Motor Impairments
Motor impairments affect the way people move. Some of the types of motor
disabilities that impact the way someone uses an app include:
• Slowness.
• Weakness.
• Stiffness.
• Loss of muscle control, which can result in muscle tightness and unpredictable
movements.
• Tremors.
As you can see, there are many different interactions to consider here when making
your app accessible. In Chapter 3, “Testing & Tools”, you’ll learn about some of the
tools people use to interact with their devices.
Try: Use your phone with your non-dominant hand. This might be frustrating
for you at first. However, you can imagine how living with an impairment
every day would allow you to learn to excel at using accessibility tools to
perform tasks without the dexterity you previously had. You can make using
these tools possible by building an accessible app.
raywenderlich.com 26
Android Accessibility by Tutorials Chapter 1: Why Accessibility
Auditory Impairments
While there are multiple classifications of hearing loss, the most important thing for
you to consider is that some people won’t be able to hear your app. This could be due
to damage to the parts of the ear, nerve damage, a total loss of hearing, loss of
hearing of high or low tones or a loss of hearing in one ear.
Either way, you’ll learn techniques for building apps for users with auditory
impairments.
Try: Spend a whole day, or even a whole week, with all the sound turned off on
your phone. This means no ringer, no alarm, no podcasts and no audio on
videos. In what places might you need to find alternative ways to use your
phone, and what might those alternatives be?
When your apps support the option to consume them in this way, using your
phone without audio can feel natural.
Neurodiversity
Neurodiversity, for the sake of this discussion, comprises the natural differences
people have when it comes to neurological structure and function. Brains are
remarkably complex, so we experience and interact with the world in wildly different
ways.
This is perhaps the broadest category discussed here. While you’re reading these,
keep in mind that there are many ways to experience every one of these.
Memory
Some people may have trouble remembering a piece of information from one task to
the next. They could forget an instruction or what an unlabeled icon does. They
might forget how they reached a specific screen in your app, or forget what to do
once there.
raywenderlich.com 27
Android Accessibility by Tutorials Chapter 1: Why Accessibility
Problem-solving
It’s extremely frustrating to experience a problem and not know how to solve it.
When designing for accessibility, you need to be clear about why a problem occurs
and what the user can do to solve it.
Attention
Keep in mind that distractions may pull users away from your content. You can help
with this by reducing the distractions you provide. Distractions can be as simple as
asking the user to confirm actions repeatedly, not showing a loading bar, or sending
the user to another website for some information.
The text you use in your app is important to the way it’s understood. With that, you
need to know that some people have difficulty reading or comprehending, so try to
reduce complexity. It can also confuse when you use sarcasm and idioms.
Math
Visual comprehension
Of the people who can see images and icons, some will not comprehend what is in
the image or what the icon represents. You can’t assume that all users understand
what a hamburger menu does. It’s helpful to include text, along with the icon or
image, to clarify what the element does.
Anxiety
When you introduce uncertainty, it can trigger anxiety in some users. It helps to be
clear about what will happen when the user performs a given action and not rush
them into performing a task.
By keeping these things in mind, you can make your app much easier and more
enjoyable to use by many people.
raywenderlich.com 28
Android Accessibility by Tutorials Chapter 1: Why Accessibility
Key Points
• To create an accessible app, you must design it so that most people can use it
without assistance.
• Accessible apps widen your audience to the 1 in 4 adults who have some type of
disability.
• Developing an accessible app makes your product better and increases developer
productivity.
• Having access to apps is a civil right, and caring about accessibility is the right
thing to do.
• Visual, motor, auditory and cognitive impairments change the way people
experience your app.
You won’t render your users burrito-less, anxious or feeling discontent with your
app.
In the next chapter, you’ll get started on fixing up a taco recipe app to make it more
accessible. Because who doesn’t love accessible tacos?
raywenderlich.com 29
2 Chapter 2: Hello,
Accessibility!
By Victoria Gonda
One of the best ways to learn is to jump right in and start applying your new
knowledge. Throughout this book, you’ll be working on making an app more
accessible. You’ll be able to apply the techniques you learn here right away, whether
you’re working on an existing app or building a new one outside of this book. You
don’t even need to finish the book to start applying the new information from each
chapter in your projects!
You’ll soon see that you already have the tools to get started and that it takes only a
couple of lines of code to make a big difference for your users.
Find the starter project in the materials for this chapter and open it in Android
Studio. Build and run the project.
raywenderlich.com 30
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
You’ll see that there are auto-advancing slides followed by recipe cards at the
onboarding stage. You can swipe the recipe cards to the right and left to save for
later or pass them up, respectively, and move to the next recipe.
raywenderlich.com 31
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
Finally, you’ll see some pop-up dialogs and a bare-bones settings screen.
As you improve the app’s accessibility, you’ll also improve the overall user
experience. When you complete this book, the app will look more like this:
raywenderlich.com 32
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
Pick the right profile at the top — there are some options:
• If you choose Project Default, you can check your lint rules into version control.
• Otherwise, if you pick Default, they will be your local rules. You can create more
profiles if needed.
For this project, it doesn’t matter which profile you use, so just pick one.
raywenderlich.com 33
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
Review the list of items below the profile selection. Look for Android ‣ Lint ‣
Accessibility. Select the checkbox at the end of each item.
Warning severity.
Click OK to save the lint settings and close Preferences. Now you’re all set to see
lint errors.
./gradlew lint
gradlew lint
Note: You can use the terminal window in Android Studio under View ‣ Tool
Windows ‣ Terminal.
raywenderlich.com 34
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
It might take a few minutes to complete. When it’s done, you’ll see in the output:
Wrote HTML report to <filename>. Open that file in your browser to see a list of
lint warnings.
Scroll down until you see Usability, Accessibility, and Internationalization. These
are the warnings that matter for this book.
Note: If you see lint errors as raw text, make sure that filename has the .html
extension.
The second way to see the results is right in your code. In the HTML output, you can
see that contentDescription is missing from fragment_discover.xml. Go to that
file and look at the ImageView named discover_button_discard. Hover your
mouse over the ImageView text.
raywenderlich.com 35
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
Phew! This is a bit of a mess with all these warnings. Good thing you’re here to fix it!
The Android system does much of the work of supporting accessibility for you.
Because of that, many of the changes you need to make take only a line or two of
code.
raywenderlich.com 36
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
For icons that act like buttons, like this one, it’s best to use a single verb to describe
the view. For this view, use Discard because you’re discarding the recipe to look at
the next. Lucky for you, there’s a String resource named shared_discard in use
throughout the app!
android:contentDescription="@string/shared_discard"
This makes it so that accessibility services, and the people who use them, know to
use this button to discard a recipe.
Notice that the description doesn’t contain the word button. The system can
decipher when a component is clickable. The system communicates that state to the
user. As a rule, you don’t need to use words like “button” or “label” in your
descriptions.
android:contentDescription="@string/shared_try_it"
Good work! That’s one more view that accessibility services can correctly interpret.
Now the user will understand this button saves the recipe to the “Try it” list.
Run the linter again and you’ll see two fewer warnings — and you only needed two
little lines!
Find the views in the following files and add the given content descriptions:
raywenderlich.com 37
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
For now, make this your practice: Pick a verb for a button that performs an action.
For other images, follow the pattern object + action + context. For example: “A
person eating a taco on a Tuesday”.
In Chapter 4, “Perceivable — Layout & Labeling”, you’ll learn more about writing
good content descriptions.
At the top of each of these, you already have the image set to thumbs-up or thumbs-
down on recipeDetailTryDiscardButton. This is where you’ll set the content
description.
recipeDetailTryDiscardButton.contentDescription =
getString(R.string.shared_discard)
To do the same for the opposite state, add this to the top of hideEditableFields():
recipeDetailTryDiscardButton.contentDescription =
getString(R.string.shared_try_it)
Great! Now, when the button changes state, the content description changes with it.
Run lint now. You’ll see fewer ContentDescription warnings — there should be three
left. You’ll handle these slightly differently from the rest.
raywenderlich.com 38
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
Ignoring Views
When you design for accessibility, you need to think about two types of content:
• The content the user uploads, which you can’t possibly know how to describe —
unless you have supernatural abilities and can predict what future users will
upload.
But seriously, how do you support accessibility for user-generated content? For
example, in the app, each recipe has a different image. Eventually, these images will
come from users, so you need to consider the problem now.
1. Ask the user to describe the image. Then you can include that description in the
API response and set it to contentDescription.
2. Tell the accessibility services that this view isn’t important for it to read so it will
skip the view.
android:contentDescription="@null"
Perfect. Now the screen reader has the information it needs about this image.
raywenderlich.com 39
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
Now, run the linter. Oh, look! There’s another case where it feels uncertain about the
content description text: decorative views.
Because it’s a decorative view, it doesn’t add any meaning. You can safely ignore
decorations using android:contentDescription="@null". This guideline applies
to elements like dividers or gradients.
You could add that here. However, you have another option!
This doesn’t need to be an ImageView. Instead, you’ll set it as a plain old View with
the color as the background. Change ImageView to View:
<View
android:background="?colorControlHighlight"
raywenderlich.com 40
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
<View
android:id="@+id/recipe_detail_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?colorControlHighlight" />
Notice that the linter warning doesn’t appear in Android Studio anymore. That’s
because accessibility services skip these View elements unless you signal that a view
is important for accessibility.
Throughout this book, you’ll learn some ways to tell the accessibility services how to
treat a plain view. Content description is only one of them.
Run the linter again. There’s one ContentDescription warning left. You’ll have the
opportunity to fix it in the challenge at the end of this chapter.
But wait! You need to learn how to handle another common warning before you can
call this chapter complete.
raywenderlich.com 41
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
KeyboardInaccessibleWidget warnings.
This warning happens when you declare a view as clickable but not focusable. When
you do this, you make the view interactive for people who tap it to perform the
action, but not for someone who’s using a keyboard or similar technology to access
it.
Often with keyboards, you first need to focus the view, then select it. If it’s not
focusable, the user can’t perform the action. Again, this is something you can fix
with only one line of code!
Open fragment_discover.xml, where all these warnings live. Find the ImageView
with the ID discover_button_discard. Add the following property to the view:
android:focusable="true"
And that’s all it takes! By adding the focusable property, you inform the system to
let keyboard users focus on it.
raywenderlich.com 42
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
While you’re at it, add the same property to the other two views in this file that need
it. These views have the IDs discover_button_try and
discovery_card_detail_button.
android:focusable="true"
Run the linter. You’ve solved so many accessibility warnings! There should be much
fewer. You’ll continue solving these throughout the book.
Build and run. It should behave the same as before when you’re not using
accessibility services. In the next chapter, you’ll learn how to use accessibility
services so you can experience the impact of your changes.
Now that you’ve gotten your hands dirty, and are hopefully ready to focus on some
theory, this chapter will pivot to bring you up to speed on accessibility guidelines.
Defining WCAG
This book teaches you the best practices for and conforms to the Web Content
Accessibility Guidelines (or WCAG) version 2.1 as the standard for accessibility.
These guidelines are an industry standard.
WCAG is exactly as the name suggests: a guideline for making your web content or
app accessible. The guidelines help you build your app so it’s consumable to a wide
range of people. It doesn’t address every user’s needs — nor does this book — but it
covers the main points and best practices.
Even though the guideline’s title suggests they are for the “web”, they’re useful for
Android engineers to follow, and here’s why:
• Used for legal requirements: Remember the legal requirements you learned
about in Chapter 1, “Why Accessibility”? Many legal battles use WCAG as the
guidelines for how to comply with accessibility laws across countries. That alone
should make it a priority for you to learn.
• Common language with others: You can use these guidelines across platforms.
This means that you can talk about accessibility using this language with iOS and
web engineers, as well as customers, product managers and designers.
raywenderlich.com 43
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
Note: As an example, the content descriptions you added help you satisfy the
first requirement:
Guideline 1.1 Text Alternatives: Provide text alternatives for any non-text
content so that it can be changed into other forms people need, such as large
print, braille, speech, symbols or simpler language.
You’ll dig even deeper into this guideline in Chapter 4, “Perceivable — Layout &
Labeling”.
• P erceivable
• O perable
• U nderstandable
• R obust
Content descriptions fall under “perceivable”. They allow your user to perceive
what’s in an image or understand a button’s purpose.
Making a view both clickable and focusable falls into the “operable” category. It lets
people using a keyboard operate your app.
raywenderlich.com 44
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
Guideline 1.1 Text Alternatives, which covers content descriptions, is level A. It’s one
of the first guidelines, and all apps should conform to it.
Note: This book will reference WCAG and the Android resources throughout.
If you’re curious enough to look into these, head to WCAG at https://
www.w3.org/TR/WCAG21/ and the Android docs resource at https://
developer.android.com/guide/topics/ui/accessibility.
• Accessible design is self-descriptive: It’s design that makes your app accessible.
Features could be accessible in and of themselves, or you could create a tailored
experience so someone using assistive technologies gets a different version of the
app.
• Universal design is a subset of accessible design, with the intent being to ensure
that everyone gets the same experience. The design is accessible by default, so you
don’t need to create a second design specifically for those using assistive
technologies.
raywenderlich.com 45
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
This book uses universal design wherever possible because it makes your user
experience consistent for all users, and it protects user privacy. With universal
design, you don’t need to pry into your users’ data to see if they use assistive
technologies.
At this early stage in the book, you’re already better equipped to start improving
accessibility in any app! Before you move on to the next chapter, here’s an
opportunity to practice what you’ve learned already.
Challenges
Challenge 1: Solve the ContentDescription
warning
Remember, the last time you ran the linter there was one more ContentDescription
warning. Now’s the time to show your stuff by solving it!
• To see the on-boarding screen again when you run the app, check Show on-
boarding in the Settings screen. Then, next time you close and open the app you’ll
see the on-boarding screen.
• If you decide to set the content description programmatically, set this view’s
properties in OnboardingPagerAdapter in OnboardingActivity.kt.
• Again, if you set the content description programmatically, make the warning go
away in the XML file by either adding a placeholder content description or by
suppressing the lint using tools:ignore="ContentDescription". If you
suppress the warning like this, it’s helpful to add a comment to clarify that it’s set
programmatically.
raywenderlich.com 46
Android Accessibility by Tutorials Chapter 2: Hello, Accessibility!
Key Points
• Android lint is a useful tool for identifying accessibility issues.
• WCAG and the Android docs are excellent resources for understanding
accessibility requirements.
• Choose universal design over accessible design so that everyone has the same
experience in your app.
Think about the huge impact you’ve already made on this app. Before your changes,
there was no straightforward way for a person using a screen reader to know how to
save a recipe, and there would be no way for someone using a keyboard to dismiss a
recipe to move to the next.
Before you can get much further with your new knowledge, you’ll need to learn more
about the common assistive technologies people use and about testing technologies
that can detect potential issues. Move on to the next chapter to fill in those gaps and
move one step closer to being an accessibility detective!
raywenderlich.com 47
3 Chapter 3: Testing & Tools
By Victoria Gonda
Accessibility services are among the many tools Android provides for users. Some
people depend on these services to view and navigate apps. Learning how to use
these tools for yourself will help you get a clear picture of how your app interacts
with these services. It will also help you develop empathy for your users who rely on
these services.
Some tools automatically detect accessibility issues in your app. They include
standalone scanners, as well as tools that integrate into your automated testing and
IDE.
In this chapter, you’ll learn about these tools and testing for accessibility so that, as
you work through the remaining chapters, you’ll be able to verify the improvements
you’re making.
To get started, you need to make sure you have these tools set up on your device.
raywenderlich.com 48
Android Accessibility by Tutorials Chapter 3: Testing & Tools
• Accessibility Suite
• Accessibility Scanner
• Voice Access
Most modern physical devices come with some of the services found in the
accessibility suite. Depending on your device, you may have some services but not
others. If you don’t see a certain service, often you can set up an emulator that has
that service and carry on.
Note: Many of these tools work better on a physical device than an emulator,
so use that option if you have it. If you’re using a physical device, you can skip
ahead to Downloading Tools.
If you already have an emulator, check the apps list to see if the Play Store is
installed. If yes, you can skip ahead to downloading. If not, follow the next steps to
learn how to set up an emulator with the Play Store.
raywenderlich.com 49
Android Accessibility by Tutorials Chapter 3: Testing & Tools
The simplest way to get the Play Store on an emulator is to create an emulator
through Android Studio. Go to Tools ▸ Device Manager, or click the Device
Manager icon in the toolbar.
raywenderlich.com 50
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Then, choose a Phone that has the Play Store icon and click Next.
Boot your new emulator and you’re ready to start downloading the tools you need.
Downloading Tools
The first thing to download is the Android Accessibility Suite, a set of tools that
people with disabilities use to navigate their devices.
If you see tools like TalkBack and Select to Speak, then you have what you need for
this book. Some phones come pre-packaged with these services.
raywenderlich.com 51
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Otherwise, head over to the Play Store and sign in with a Google account. Search for
and download Android Accessibility Suite.
Once the downloads finish, review the full suite of tools in the Accessibility Settings
at Settings ▸ Accessibility. You’ll learn how to use many of these tools in this
chapter.
You need one more service. In the Play Store, search for and download Accessibility
Scanner.
Finally, install Voice Access. This one is optional, as it may not be available on
emulators or older devices. Search for Voice Access in the Play Store. If it’s there,
download it.
raywenderlich.com 52
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Note: Consider these optional settings to make navigation easier: Turn on the
Accessibility Menu at Settings ▸ Accessibility ▸ Accessibility Menu, and turn
on three-button navigation at Settings ▸ System ▸ Gestures ▸ System
Navigation. Keep in mind that this is not available on some emulators.
Note: When working with the settings below, some emulators and devices may
have subtle variations in terms, features and locations in settings.
Select to Speak
The first service you’ll try is Select to Speak. Go to Settings ▸ Accessibility ▸ Select
to Speak and toggle the Select to Speak shortcut switch to on. You’ll see a
permissions dialog pop up. Tap Allow.
raywenderlich.com 53
Android Accessibility by Tutorials Chapter 3: Testing & Tools
To use this service, tap the Accessibility icon in the navigation bar.
Note: On some devices you may need to press an accessibility (stick figure
person) icon in the navigation bar instead.
This will bring up a control. Tap the Play triangle so it reads everything on the
screen. Pick your favorite app and tap the triangle to try it out.
raywenderlich.com 54
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Pretty neat! Examples of people who might use this service include those with vision
impairments and those who struggle with reading.
Try it out as much as you like. Then, go back to Settings and turn it off the same way
you turned it on before.
Switch Access
While Select to Speak allows you to read items on the screen, Switch Access enables
you to navigate. It’s helpful for users who have limited mobility.
You generally use Switch Access with special hardware that has two or more buttons.
One button moves to the next element on the screen, while the second selects the
current element.
Example of a switch.
Most people don’t have this kind of switch lying around, so you’ll set up your device
to use the volume keys as buttons.
Note: Not all devices have this option. If you don’t see the option to assign
keys and you’re working with a physical device, you can try Camera Switches
(https://support.google.com/accessibility/android/answer/11150722).
Find Switch Access in the Accessibility Settings and go to Switch Access ▸ Settings
▸ Assign switches for scanning. Tap the option for Select.
raywenderlich.com 55
Android Accessibility by Tutorials Chapter 3: Testing & Tools
A screen will pop up that allows you to assign a button for Select.
Note: You can choose other buttons if you like. If you’re using an emulator or
have an attached external keyboard, you can even use a key on your keyboard.
You’re all set to use Switch Access! Go back to the root Switch Access screen in
Settings and toggle on Use Switch Access. Try using Volume Up to walk through
onscreen items, and Volume Down to “tap” an item.
After you’ve navigated a couple of views, go back to the Switch Access view and turn
off the service.
raywenderlich.com 56
Android Accessibility by Tutorials Chapter 3: Testing & Tools
TalkBack
TalkBack combines reading and navigating into one service. With TalkBack, you can
use gestures or a keyboard to navigate the screen, and the device reads the contents
out loud. This tool is great for users with low or no vision.
Find TalkBack in the Accessibility Settings and toggle the switch on. If this is your
first time turning TalkBack on, you’ll see a tutorial — go through it. If you don’t see
the tutorial, you can still access it. Go to the TalkBack screen then select Settings ▸
TalkBack tutorial.
If you don’t use the tutorial, here are the basic gestures to know:
Try swiping left and right to move around the screen and double-tapping to select.
When you’re done, navigate back to the TalkBack screen and double-tap on the
switch to turn it off.
Note: You can turn TalkBack on and off via the command line using ADB, too.
To turn TalkBack on:
adb shell settings put secure enabled_accessibility_services
com.google.android.marvin.talkback/
com.google.android.marvin.talkback.TalkBackService
It helps to set up an alias if this is your preferred method to turn TalkBack off
and on.
Think back to all the content descriptions you added in Chapter 2, “Hello,
Accessibility!” for services like TalkBack. Now you can see and hear why they are
crucial to some users.
raywenderlich.com 57
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Go to TalkBack settings and find Gestures. Look at the list of possible gestures. For
example, you can swipe up then down to focus the first item on the screen.
You don’t need to memorize these as long as you know the basics:
• Double-tap to select
TalkBack Settings
There are more settings available. If you have developer options turned on, you can
set it so that the content that’s read is also printed onscreen. To turn on developer
settings, go to Settings ▸ System ▸ About device (on an emulator, this will be
Settings ▸ About Emulated device) and tap the build number seven times.
To make the device display the text it’s reading, go to TalkBack settings, scroll
down and select Advanced settings ▸ Developer settings then toggle on Display
speech output.
If you’re feeling brave or well-practiced with TalkBack, try dimming the screen while
TalkBack is on to simulate vision impairment. To turn this on, with TalkBack
enabled, swipe down and to the right to open the Global Context menu. Select Hide
screen. This will make the screen dark, preventing you from seeing the items you’re
selecting. To turn it off, swipe down and right again, then select Show screen.
raywenderlich.com 58
Android Accessibility by Tutorials Chapter 3: Testing & Tools
On this screen, under Navigation actions, you can see which keys map to which
actions. The most important ones to know are:
Voice Access
Voice Access is a hands-free way to control a device. By saying commands like “Type
Hello World”, “Back” and “Submit”, a user can type in an edit field, close the
keyboard and submit a form.
You should have Voice Access downloaded, so go to Voice Access in the Accessibility
Settings to turn it on. Go through the tutorial when prompted.
There are three ways to navigate using Voice Access. You can say the text of the
element, say the number that’s next to it, or use a grid system to narrow down a
view.
Adjusting Size
When you live with vision limitations or your device is far away, adjusting the size of
what’s onscreen can do wonders. Android has three ways to do this.
raywenderlich.com 59
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Font Size
You can scale the font size across apps. Go to Display size and text in Accessibility
Settings. This might also be called “Font size” or “Text and display” depending on
your device. Use the slider at the bottom of the screen to scale the text to Largest.
Use a few of your favorite apps to see how they look. Text that used to fit on one line
might now be on two lines or be truncated.
Display Size
Changing the display size is much like scaling the text. The difference is that it also
changes the size of non-text elements, such as icons. Go to Display size and text in
Accessibility Settings to try it. This might also be called “Display size” depending on
your device.
Magnification
Unlike scaling, which has a universal effect, magnification allows you to zoom in on
any screen. Go to Magnification in Accessibility Settings. If you have the option, go
to Magnification shortcut. Turn the service on.
Try it out. Tap the shortcut to zoom in then use two fingers to scroll or even zoom in
further. Tap the shortcut again to un-zoom.
Modifying Colors
Changing colors can provide a better experience for users with vision disabilities.
People may also use these options because of their preferences. Try out each of
them, one at a time, turning off one before you move to the other.
Dark Theme
Did you know that the dark theme is also an accessibility feature? Since Android 10,
you can activate dark mode from Settings ▸ Display ▸ Dark Theme but you can also
set it in Settings ▸ Accessibility ▸ Color and motion ▸ Dark Theme on some
devices. Surely, you already know which setting you prefer!
raywenderlich.com 60
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Note: While these options might be availbe on your emulator, there are some
emulators where you wont see a change when you turn them on.
Color Inversion
Somewhat related to the dark theme is Color inversion. As the name suggests, this
takes all the colors on the screen and inverts them. Unlike the dark theme, it also
inverts photos. Try turning on Color inversion at Settings ▸ Accessibility ▸ Color
and motion. Note that on some devices this may be under Settings ▸ Accessibility
▸ Color and motion.
Color Correction
The color correction setting can help with color blindness. Turn on Color
correction in Settings ▸ Accessibility ▸ Color and motion. Try the different types
of color correction to see how it changes the colors on your screen.
Did you notice any places where low contrast made it more challenging to see
something?
Showing Captions
Newer devices come with Live Caption. This feature detects when the device plays
audio with speech and displays captions. Like the other services, you enable this in
Accessibility Settings. Look for Caption, turn it on then play a podcast or other
audio with talking in it.
raywenderlich.com 61
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Disabling Animations
Although some users love animations, for others, they can be distracting or even
nauseating. That’s why there’s an option to turn them off. Go to Settings ▸
Accessibility ▸ Color and motion ▸ Remove animations and toggle the switch on.
On some devices this may be under Settings ▸ Accessibility ▸ Text and display ▸
Remove animations The change is typically subtle. Notice that when you switch
apps, you no longer see the animated transitions.
Accessibility Services
Many of these tools hook into the same accessibility services. These services
communicate with app views to understand the content and what actions are
possible. They know the bounds of each view and can decipher if something
important changed.
You’ll learn more about how to directly communicate with these services in Chapter
10, “Robust”. Until then, you’ll inform the accessibility services about your views in
similar ways to the content descriptions from Chapter 2, “Hello, Accessibility!”.
Lint Checks
In Chapter 2, “Hello, Accessibility!”, you learned how lint checks help you improve
your app. Lint enables you to maximize accessibility by providing feedback from an
early development stage, right in your IDE.
Espresso Tests
Espresso, one of the leading libraries used for UI tests on Android, also includes
accessibility checks. You don’t even need to write additional tests to use it! It runs
alongside your existing Espresso tests.
Open up the Taco Tuesday project in Android Studio. You can either continue where
you left off or work with the starter project for this chapter.
raywenderlich.com 62
Android Accessibility by Tutorials Chapter 3: Testing & Tools
There’s a UI test already written for you. Open DiscoverFragmentTest.kt and try
running it by clicking the Play button in the gutter next to the class name.
Note: You may need to turn off animations on your device to run these tests.
To add accessibility checks, start by adding the accessibility Espresso add-on library.
In the app level build.gradle, add this to the list of dependencies.
androidTestImplementation
"androidx.test.espresso:espresso-accessibility:3.4.0"
Sync the Gradle file. Now, go back to DiscoverFragmentTest and add this code to
the bottom of setup():
AccessibilityChecks.enable()
.setRunChecksFromRootView(true)
Another option is to enable these checks in your test runner instead of enabling
them for all your tests.
raywenderlich.com 63
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Until then, you’ll instruct the Espresso Accessibility Library to ignore some issues.
Add the following to the AccessibilityChecks method chain you have, importing
org.hamcrest.Matchers.anyOf:
.setSuppressingResultMatcher(
anyOf(
matchesViews(withId(R.id.discover_button_discard)),
matchesViews(withId(R.id.discover_button_try))
)
)
This suppresses any accessibility errors with the IDs discover_button_discard and
discover_button_try. You can use any ViewMatchers here, so it’s possible to
match by any view attribute or a collection of views.
Accessibility Scanner
Remember the Accessibility Scanner you downloaded near the beginning of this
chapter? Now you get to try it.
Head back to Accessibility Settings and find Accessibility Scanner. Toggle it on and
accept all the prompts. A blue check mark will show up on the screen when you exit
Settings.
Tap the blue check mark to scan the screen. Pick Snapshot to scan what’s currently
onscreen or Record to continuously scan as you move through the app. For this
exercise, tap Snapshot.
raywenderlich.com 64
Android Accessibility by Tutorials Chapter 3: Testing & Tools
You’ll land on a results screen that shows boxes around all the service’s accessibility
suggestions.
Note: Other scanners do a similar job. For example, you can download Axe
from the Play Store and try it out.
raywenderlich.com 65
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Manual Testing
You’ve already been manually testing in this chapter, and it’s one of the most reliable
ways to test your app. Use the tools you learned above, such as TalkBack, to see how
your app behaves. Is something hard to see or do with one of these tools? If so, you
know there’s a potential issue.
Although tools such as Espresso tests and the Accessibility Scanner adeptly spot
potential pitfalls, you don’t want to rely on them. They lack a comprehensive picture
of how your app behaves. Only humans can assess your app’s accessibility.
Experimentation, QA and user testing are the ultimate accessibility tests.
If you’re on a small team, accessibility usually becomes the individual engineers’ and
designers’ responsibilities. Although accessibility has to be juggled with other day-
to-day tasks, a small team has the advantage of tight feedback loops. You must set
standards, boundaries and clear expectations for accessibility. You need to be
intentional in your approach.
You have more flexibility if you’re on a larger team — especially if you’re large
enough to have designated engineers, contractors and accessibility QA testers. Large
teams have the advantage of more resources to dedicate to accessibility. The
challenge for large teams is communication. It’s more challenging to keep several
people on the same page and to clearly define roles and responsibilities when many
hands are involved. In addition to defining roles, you have to establish processes for
the team to follow. Each team member must know what to do, when to do it and who
needs to sign off on the work.
raywenderlich.com 66
Android Accessibility by Tutorials Chapter 3: Testing & Tools
Regardless of your team size, these questions will help you put together your testing
strategy:
• How much time and which resources do you have to put towards this?
• What level of conformity do you want to have? Reference the WCAG standards
from Chapter 2, “Hello, Accessibility!” for this question.
• Which screens take priority? Are your highest trafficked or entry screens
accessible? Which items from your roadmap require extra accessibility work?
These are questions to get you thinking about how building accessibility into your
team’s daily routine might look. They’ll also help you define what’s “good enough” at
a given time. There’s much more about this in Chapter 12, “Getting Your Team on
Board”.
Key Points
• Download Accessibility Suite and Accessibility Scanner from the Play Store.
• Select to Speak, Switch Access, TalkBack and Voice Access are all ways of viewing
and navigating your device.
• Users can change the size of views with magnification and adjust the font size and
display size.
• Captions can make audio accessible for those with hearing impairments.
• Using the accessibility tools for yourself is the ultimate way to understand your
app’s accessibility.
Now that you’ve explored some accessibility tools, it’s time to dive deeper and learn
more about content descriptions and layouts to make the app more perceivable.
raywenderlich.com 67
4 Chapter 4: Perceivable —
Layout & Labeling
By Victoria Gonda
In this chapter, you’ll continue making improvements to Taco Tuesday. By the end of
the chapter, you’ll have applied what you learned to give the app helpful
descriptions, labeling and layouts that are more perceivable for people using screen
readers and other assistive technologies.
In Chapter 2, “Hello, Accessibility!”, you learned how to add content descriptions and
in Chapter 3, “Testing & Tools”, you learned about screen readers. You should read
both chapters before starting this one.
To learn these topics, you’ll continue working on the Taco Tuesday app. Either open
the project you’ve been using in the previous chapters or find and open the starter
project in the materials for this chapter.
raywenderlich.com 68
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Defining Perceivable
Perceivable is the first category that the WCAG defines for how to make your app
accessible. Here’s the definition provided in the WCAG documentation:
This means that no matter if someone is consuming your app visually or through
audio or touch, they can identify what’s on the screen.
Throughout this book, you’ll see these quotes from the WCAG documentation to
guide you on your way and give you a reference if there’s a topic you’d like to look
deeper into. When it applies, you’ll also see the level they rated the guideline so you
know if you’re reaching Level A, AA or AAA conformity by applying it.
To focus on perceiving the app in a way you might not normally, this chapter will
have a heavy focus on screen readers.
Before moving on, it’s good to have a rough idea of how screen readers work. Here
are a couple of tips on screen reader behaviors to help inform the decisions you make
for your app:
1. When screen readers traverse your screen, they read out text and content
descriptions. They also announce an item, such as a button, and any actions that
you can perform.
2. Readers typically traverse a screen from the top down and from start to end.
However, this isn’t always the case — sometimes they follow the view hierarchy.
While the experience is consistent on a given device, it can vary widely across
devices.
3. Finally, readers often have shortcuts to jump to specific parts of the screen. For
example, if you have headers, the user can skip ahead to the next header and
avoid hearing text that doesn’t interest them.
raywenderlich.com 69
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
You’ll use TalkBack and the Accessibility Scanner to verify your work. For a
refresher on how to use these tools, go back to Chapter 3, “Testing & Tools”.
Guideline 1.1 Text Alternatives: Provide text alternatives for any non-text
content so that it can be changed into other forms people need, such as large
print, braille, speech, symbols or simpler language.
This guideline has one criterion that you need to meet. Lucky for you, you can largely
meet this one using content descriptions.
Level A
To round out your understanding, here’s a review of what you covered in Chapter 2,
“Hello, Accessibility!”.
In that chapter, you used a linter to identify non-text elements that were missing a
content description. This lets accessibility services know what to do with icons like
the thumbs-up Try It button.
Build and run the Taco Tuesday app. Run TalkBack on the main screen to hear the
content descriptions you added. In fragment_discover.xml, remove the
contentDescription attribute from the ImageView with the ID
discover_button_discard and run it again to notice the difference.
raywenderlich.com 70
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Imagine if you couldn’t see the screen. That description makes so much of a
difference!
android:contentDescription="@string/shared_discard"
This fixes the temporary change you made so you could see how it behaves with the
screen reader.
You used this on the header image on the main Discover screen. Now, follow the
same exercise you did above; try out TalkBack with and without
contentDescription set on the view with ID discover_recipe_image in
fragment_discover.xml.
android:contentDescription="@null"
There are two different ways you can signal accessibility services that they should
ignore a view. Often, they behave the same way but they do behave slightly
differently in some cases:
raywenderlich.com 71
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
android:contentDescription="@null"
In many cases, when used on a non-textual element, accessibility services will ignore
the view. In some cases, because this view is still available to the screen reader,
accessibility services will still read out some text while exploring the screen. This is
especially true if you’re using this on a textual element, such as hiding decorative
text. The reader will still announce the decorative text.
This app includes a good place to apply this option. With TalkBack off, make sure
you have some recipes saved in the app along with the Thanksgiving Tacos recipe,
then go to the list. Notice you can swipe to discard an item.
raywenderlich.com 72
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Now, view the Thanksgiving Tacos recipe with TalkBack turned on. Notice that it
reads Discard along with the rest of the card. The same goes for the rest of the
favorite recipes.
android:importantForAccessibility="no"
Build and run. Look at the Thanksgiving Tacos view with TalkBack again. This time
the reader ignores Discard.
raywenderlich.com 73
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Describing Icons
Icons are often used as an actionable button or to show a state. When an icon is used
as a button, you often use a verb for the description. If you have a pencil icon button
to edit a contact, Edit contact is much more meaningful than Pencil. You want to
describe what the icon does.
When you have an icon representing a state, the description should generally
describe what the state is. For example, you might have a padlock icon where the
state, and therefore the content description, is Private.
If you have a toggleable icon that’s both actionable and shows state, you usually
describe the state it represents. This is especially true when you’re using a Switch or
Checkbox with a custom-selectable drawable. The system will know to say whether
it’s checked or not. The accessibility service would read: “Favorited, checked” or
“Favorited, unchecked”.
Describing Text
In most cases, you don’t need to add content descriptions to text. The text should
speak for itself. Exceptions include situations where you have a compound drawable
that the user should understand along with the text, or if you have symbols in the
text that the user should perceive differently.
For example, if you have the text: “$5/month” you might want the content
description to read “$5 per month.”
Describing Images
Perhaps one of the hardest types of items to describe are images. There can be a lot
of content in a single image. How much should you share?
You want to be concise enough that it’s consumable, while descriptive enough that
the user understands all the essential parts of the image. One pattern that can help
you achieve this is object-action-context.
To follow this pattern, you start by describing the main object of the photo. Then,
you describe any action that the object might be doing, following the context. An
example of this might be “A person eating a taco at a home dining room table.”
You can judge how much detail your user needs. If you need to add more detail, try
not to be repetitive. Either include the details inline like “A happy person eating a
fish taco at a blue home dining room table with some friends.”
raywenderlich.com 74
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Or, start with the object-action-context pattern, followed by the details. “A person
eating a taco at a home dining room table. The person has long hair and is happy.”
You can also apply these guidelines to GIFs and some videos. As you’re writing these
content descriptions for your app, keep in mind that you should treat them as copy.
People consume these descriptions the same way as other copy in your app.
That’s a lot of information about text alternatives. Now, it’s time to switch gears and
talk about layouts.
At a high level, you want to organize your information logically. Keep in mind that
most screen readers (and humans!) start at the top of the screen, and work their way
down. There are lots of other ways you can improve your layout as well.
Notating Headers
Using headers is an effective way of organizing your content. It allows a person to
identify and skip directly to the section that interests them. It associates the content
in that section with a common topic.
Screen readers also use this organization. A person using assistive technology can
navigate and perceive the content in your app more easily if you provide this
structure. Headers are one way of meeting Success Criterion 1.3.1:
Level A
raywenderlich.com 75
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Open the app and look at the details of a recipe. There are sections for different parts
of the recipe such as the base layer and mixin. These sections each have a label that
you can treat as a header.
android:accessibilityHeading="true"
You might see a warning that this attribute is only available on API level 28 and
higher. That’s OK! There’s a way to accomplish the same thing using
AccessibilityNodeInfoCompat. You’ll learn more about this class later in the book.
Now, for accessibility services that support it, users can jump between headers. The
header is also announced as a header.
While using TalkBack, you can navigate through the headings by opening the local
context menu using the swipe up then to the right gesture or Alt-Shift-Space with
the keyboard.
Build and run to see your changes. Go to the details for any recipe. With TalkBack
turned on, open the local context menu and pick Heading. Navigate this screen as
you would normally, this time skipping from heading to heading.
raywenderlich.com 76
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Note: If you don’t see a “Headings” or “Navigation” option, you may need to
go to the TalkBack settings an add it under Customize TalkBack menu.
When you’re done, open the local context menu again and switch back to Default so
you can move on to the next topic.
Level A
For an example of how this looks, imagine you have a label and a value. Rather than
requiring the user to read Total, then swipe to the next item to hear $5.43, they can
hear the group: Total: $5.43, altogether.
You can group items by making the shared parent view focusable. Try this by
grouping the nacho and spice rating bars with their labels that show on the Detail
screen when you have a recipe saved.
raywenderlich.com 77
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
android:focusable="true"
android:focusableInTouchMode="false"
Now, when you use TalkBack on these items, it selects the heading and ratings
together, rather than traversing them separately. Note that the rating is still missing
a content description. You’ll take care of that custom view in Chapter 10, “Robust”.
Success Criterion 1.3.4 Orientation: Content doesn’t restrict its view and
operation to a single display orientation, such as portrait or landscape, unless
a specific display orientation is essential.
Level AA
Imagine having your device mounted and not being able to change the orientation.
For example, you could have a motor disability and have your phone mounted to a
wheelchair or you could have it mounted to the dashboard of your car. Imagine your
navigation app not rotating to match the orientation of the device. This makes the
app much more difficult to use.
raywenderlich.com 78
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Right now, Taco Tuesday’s configuration locks it in portrait. To allow rotation, head
to AndroidManifest.xml.
Build and run. You can now rotate the device and see the contents rotate as well.
Most of the screens even look okay! The exception is the Discover view. The cards are
way too tall for the screen.
Note: Make sure you enable the Auto-rotate option on your device to be able
to change screen orientation.
<dimen name="discover_card_width">424dp</dimen>
<dimen name="discover_card_height">230dp</dimen>
raywenderlich.com 79
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
This changes the card width and height for landscape mode. Build and run to see the
improvements.
Labeling Inputs
Inputs are a place for potential confusion. When working with them, it’s important
to make it clear what the input does.
Success Criterion 1.3.5 Identify Input Purpose: The purpose of each input
field collecting information about the user can be programmatically
determined.
Level AA
On the bottom of the details screen of a saved recipe, there’s a place to add notes.
raywenderlich.com 80
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Right now, the Notes label is a separate TextView from the input field. With this
layout, you need to let the screen reader know that this is a label for the EditText.
To do this, use the labelFor attribute.
android:labelFor="@+id/recipe_detail_notes_edit_text"
Build and run the app. Now, turn TalkBack on and select the EditText. It reads “Edit
box for notes”, where before it wouldn’t describe what the edit box was for.
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/recipe_detail_notes_input_layout"
style="@style/
Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="@string/recipe_detail_hint_notes">
<com.google.android.material.textfield.TextInputEditText
... />
</com.google.android.material.textfield.TextInputLayout>
This creates a wrapping TextInputLayout. Note that it has a hint to describe what
the input is for.
raywenderlich.com 81
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Because you show and hide this view depending on the saved state, you need to
update this logic before you can run the app. Open RecipeDetailFragment.kt and
find showEditableFields() and hideEditableFields().
recipeDetailNotesEditText.visibility = View.VISIBLE
recipeDetailNotesLabel.visibility = View.VISIBLE
recipeDetailNotesInputLayout.visibility = View.VISIBLE
recipeDetailNotesEditText.visibility = View.GONE
recipeDetailNotesLabel.visibility = View.GONE
recipeDetailNotesInputLayout.visibility = View.GONE
All this does is show and hide your new TextInputLayout, rather than the separate
label and EditText.
Build and run. Not only does the input have a fancy new style, but it also helpfully
reads: Edit box, notes when using the screen reader.
raywenderlich.com 82
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Guideline 1.4 Distinguishable: Make it easier for users to see and hear
content including separating foreground from background.
While other chapters will cover most of the criteria under distinguishable, one way
to make your text easier for users to see is closely related to the layouts discussed in
this chapter.
The way you lay out your views affects whether people can still read the text when
it’s scaled.
Success Criterion 1.4.4 Resize text: Except for captions and images of text,
text can be resized without assistive technology up to 200 percent without loss
of content or functionality.
Level AA
On your device, go to Settings ‣ Accessibility and look for Font size. Depending on
your device, this could be at the root level or under Display size and text ‣ Font
size and style. Scale the font size up to Largest, then return to the Taco Tuesday
app.
You can see that all the text is now larger! This is because, when you set the font size
on all these views, you use sp for the unit: scalable pixels. If you were to use
another unit, such as dp or density pixels, they wouldn’t scale. Because of this, you
always want to use scalable pixels when defining text size.
Once you’ve taken care of that, you need to make sure your view’s height scales
correctly. You shouldn’t set a static height on your text views — otherwise, you could
have some text cut off.
raywenderlich.com 83
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Take a look at your saved recipes list. If you have a recipe with a long name, it cuts
off at the bottom.
The first resolution for this is to make sure the height is wrap_content. Go to
item_try_it_recipe.xml and find the view with the ID item_recipe_title. Notice
that the height is set to 100dp? Change the height to wrap_content:
android:layout_height="wrap_content"
Now, build and run the app. The text no longer cuts off.
raywenderlich.com 84
Android Accessibility by Tutorials Chapter 4: Perceivable — Layout & Labeling
Key Points
• The first thing to consider when making your app accessible is whether it’s
perceivable.
• To make your app accessible, you should support all screen orientations.
• By using scalable pixels and avoiding static height text views, you allow for scaling
text.
You’ll continue this journey to make the app more perceivable in the next chapter,
where you’ll learn how to handle cues such as animation and color indicators.
raywenderlich.com 85
5 Chapter 5: Perceivable —
Time-Based Media & Cues
By Victoria Gonda
Video, audio, animation and instructions are vital parts of your app’s experience. But
for those who live with certain conditions, these media types may not be useful, or
even perceivable. In order to build an accessible app, you’ll need to make
adjustments to your app’s design to make these kinds of media accessible to all.
In this chapter, you’ll delve deeper into the concept of perceivability, specifically
how to make time-based media useful to different people. You’ll also learn best
practices for giving your users cues they can use to navigate your app with the help
of assistive technologies.
raywenderlich.com 86
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
That thought brings you to the prevailing WCAG guideline for this chapter:
There are many ways you can provide these types of media. For prerecorded audio,
you can have on-screen captions. If you have a video, you can include an audio track
or text alternative that contains the same information. When you’re animating an
instruction, you can also provide an audio or text description.
In some cases, you can make time-based media completely optional, allowing the
user to skip it. Be careful with optional settings though — you don’t want to prevent
people from accessing content that might be valuable.
Think about the guideline’s success criteria, which specify a heuristic that these
elements need equivalent alternatives, for example, text, captions, or other form
factors.
Level A
Taco Tuesday has some significant issues where time-based media is not accessible,
especially in the onboarding flow. Once again, you’ll improve the app so that you can
learn.
Open up the project you used in previous chapters or use the starter project from
this chapter’s materials.
raywenderlich.com 87
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
1. You could have a video that shows the different actions you can take. But without
an equivalent audio element to this video, your onboarding flow will be
inaccessible to people who cannot see the video. To address this, you can add an
audio track to the video that describes the instructions or add text for the user to
read.
2. You could have an audio track that follows some fun animations. But if the
animations don’t convey the same information that the audio does, then your
process will be inaccessible to those who can’t hear it. To make it accessible, you
need captions or other text.
3. You could already have text to accompany your time-based media, but the media
advances and the text vanishes faster than some people can read it. To make the
flow more accessible, you could add controls so that the user can manage the
pace.
While there are other options, Taco Tuesday currently suffers from the third issue. It
has instructional text and pages of animated, self-advancing instructions that run
regardless of whether the user is ready.
raywenderlich.com 88
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
// val sharedPref =
PreferenceManager.getDefaultSharedPreferences(this)
// val showOnboarding = sharedPref.getBoolean("onboarding",
true)
// if (showOnboarding) {
OnboardingActivity.startActivity(this)
// finish()
// }
With that, you’ve enabled the onboarding flow to run every time. Remember to
uncomment it when you’re done with this chapter, so you don’t find yourself
annoyed by the constant onboarding flow!
The onboarding flow uses a pager where each page contains an image and some text.
It auto-advances after five seconds, and there are no buttons to control it.
raywenderlich.com 89
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
Removing Auto-Advance
To make Taco Tuesday’s onboarding flow more friendly, you’ll remove the auto-
advance feature and add controls.
For this step, you’ll get to delete some code! Since the plan is to put the user in
control of when onboarding advances to the next page, you’ll remove the logic that
makes it advance.
lifecycleScope.launch(Dispatchers.IO) {
val options = resources.getStringArray(R.array.pop_up_options)
while (isActive) {
delay(5000) // 5 seconds
withContext(Dispatchers.Main) {
if (binding.onboardingPager.currentItem == NUM_PAGES - 1) {
MainActivity.startActivity(this@OnboardingActivity)
this.cancel()
} else {
binding.onboardingPager.currentItem++
}
}
}
}
This code would wait five seconds and then advance to the next page. If it was
already on the last page, it would open the MainActivity. But now it is gone.
Build and run. Use the settings so that you can view the onboarding flow. Note how
the auto-advancing feature is gone, and you have as much time as you need to view
the instructions.
Now that you’ve had fun deleting somebody else’s code, it’s your turn to add code.
raywenderlich.com 90
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
Adding Controls
In this section, you’ll implement logic that gives your user a straightforward way to
advance to the next page. First, you’ll add the layout for a Next button.
<com.google.android.material.button.MaterialButton
android:id="@+id/onboarding_next_button"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/space_normal"
android:text="@string/onboarding_next"
android:textColor="?colorOnPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
But now the pager might overlap the button. So you need to replace this attribute on
the ViewPager2:
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/onboarding_next_button"
This constrains the pager to the top of the Next button. Build and run, or just look at
the Design view to see what it looks like.
Next button.
Now you need a click listener for this button.
raywenderlich.com 91
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
binding.onboardingNextButton.setOnClickListener {
if (binding.onboardingPager.currentItem == NUM_PAGES - 1) {
MainActivity.startActivity(this)
} else {
binding.onboardingPager.currentItem =
binding.onboardingPager.currentItem + 1
}
}
With this code, you’re making it so that the pager will advance when you click Next.
If you’re already on the last page, it will go to the MainActivity. Build and run to
see that everything is working as expected.
While you could stop here, you’d be depriving people of the ability to go back in the
onboarding flow. You’ll add a Back button to improve the experience.
<com.google.android.material.button.MaterialButton
android:id="@+id/onboarding_back_button"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/space_normal"
android:text="@string/onboarding_back"
android:textColor="?colorOnPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
binding.onboardingBackButton.setOnClickListener {
binding.onboardingPager.currentItem =
binding.onboardingPager.currentItem - 1
}
But what if you’re on the first page? Your new Back button would probably crash the
pager because there is no previous page. You should hide this button on the first
page.
raywenderlich.com 92
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
And when you’re on the last page, the Next button doesn’t make sense. It should
have text that describes what it actually does.
You can address both issues with a listener that hides the Back button when you’re
on the first page and changes the text for the Next button on the last page.
binding.onboardingPager.registerOnPageChangeCallback(
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
binding.onboardingNextButton.text =
if (position == NUM_PAGES - 1) {
getString(R.string.onboarding_done)
} else {
getString(R.string.onboarding_next)
}
binding.onboardingBackButton.visibility =
if (position == 0) {
View.GONE
} else {
View.VISIBLE
}
}
}
)
Build and run. Open up the onboarding flow and notice how the buttons change as
you flip back and forth between pages.
Next up, you’ll learn about other improvements you can make with cues.
raywenderlich.com 93
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
Giving Cues
Another important part of onboarding is what you’re saying. How do you make sure
your instructions are meaningful? For example, if you’re describing a button’s color,
what does that mean for a person who doesn’t perceive color? This brings you to the
second criterion you’ll explore in this chapter:
Level A
While attributes such as colors and shapes can be used, you should not rely on them
to draft quality cues.
Grayscale buttons.
You might be thinking that giving the buttons a distinct shape would address the
issue. Then the reader would say, “Tap the green triangle to save this recipe”.
Unfortunately, calling out a shape won’t help people with severe vision impairments.
raywenderlich.com 94
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
You may have noticed the ambiguous directions in the pager: “Orange to the right,
tacos in sight”!
Orange what? What if you can’t see orange? What if you also can’t see the image to
give you a hint about what this means?
Clearly, Taco Tuesday’s onboarding is not meeting success criterion 1.3.3. That’s
fortunate for you because you’ll get to make it better and learn a few things along
the way.
The first is “Orange to the right, tacos in sight”! This instruction means to say that
you should swipe the orange card to the right to save it. You need the description to
be more specific and less poetic.
Replace the onboarding_try_it value with: Swipe the orange recipe card to
the right to save it to try later.
You can follow the same logic to replace the instruction “Orange to the left, move on
to the rest”.
Replace the string named onboarding_discard with: Swipe the orange recipe
card to the left to say \"no thank you!\" to a recipe.
Finally, the third instruction reads: “Green is keen to lead the way”. This gives little
information at all!
Replace the value of onboarding_view_list to be: Then, you can view the list
of recipes you want to try.
Your new instructions are much more descriptive, but you’re going to improve them
further!
raywenderlich.com 95
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
Remember that some people are not able to swipe. And the instructions don’t inform
the reader they can save a recipe from the detail screen.
Run the app and notice where the button shown below is and what it looks like. Look
for it in the details view — you can get there by clicking the view icon from the
discover screen or the list of saved recipes.
com.google.android.material.button.MaterialButton
Now you’re working with a proper button where you can use a compound image with
text.
android:src="@drawable/ic_baseline_thumb_up_24"
android:text="@string/shared_try_it"
app:icon="@drawable/ic_baseline_thumb_up_24"
raywenderlich.com 96
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
When you look at the Design view, this button now has some descriptive text along
with the thumbs-up icon.
Try it button.
recipeDetailTryDiscardButton.setImageDrawable(
ResourcesCompat.getDrawable(resources,
R.drawable.ic_baseline_thumb_down_24,
requireContext().theme))
recipeDetailTryDiscardButton.text =
getString(R.string.shared_discard)
recipeDetailTryDiscardButton.icon =
ResourcesCompat.getDrawable(resources,
R.drawable.ic_baseline_thumb_down_24,
requireContext().theme)
This makes it so that when the recipe is already saved, the button gives the user the
option to discard it.
Next, for the reverse case, delete this statement from hideEditableFields():
recipeDetailTryDiscardButton.setImageDrawable(
ResourcesCompat.getDrawable(resources,
R.drawable.ic_baseline_thumb_up_24,
requireContext().theme))
recipeDetailTryDiscardButton.text =
getString(R.string.shared_try_it)
raywenderlich.com 97
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
recipeDetailTryDiscardButton.icon =
ResourcesCompat.getDrawable(resources,
R.drawable.ic_baseline_thumb_up_24,
requireContext().theme)
Now, when a recipe is not saved, the button allows the user to save it to try later.
First, you need to write and add the message. In strings.xml, add the following line:
Then, add the new image resource to the project. Look for it in this chapter’s
materials assets ▸ onboarding_details.xml. Add this new image to the drawable
folder of this project.
You also need a content description for your image if you chose to add it during the
challenge in Chapter 2, “Hello, Accessibility”.
Go to OnboardingActivity.kt and find the companion object with the pages list.
Add the following to the list of pages right after the onboarding_discard item:
OnboardingItem(
R.drawable.onboarding_details,
raywenderlich.com 98
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
R.string.onboarding_details,
R.string.onboarding_details_description
),
Finally, update NUM_PAGES to use a computed getter, so it always has the correct
number of pages:
Build and run to see your new onboarding page. And enjoy how much more
accessible your onboarding is!
raywenderlich.com 99
Android Accessibility by Tutorials Chapter 5: Perceivable — Time-Based Media & Cues
Key Points
• Time-based media such as video, audio and animations, must be accompanied by
alternatives.
• Alternatives to visual media can be text or audio, and alternatives to audio can be
equivalent visuals.
• Users must be able to control media that’s important for them to understand. You
need to provide a way for them to go back and revisit something
When you’re unsure how to handle something, remember to lean on the WCAG,
which offers ideas in addition to guidance: https://www.w3.org/TR/WCAG21/#time-
based-media
When you’re ready to move on, you’ll finish up this three-chapter series about
perceivability in the next chapter by digging into colors.
raywenderlich.com 100
6 Chapter 6: Perceivable —
Colors
By Victoria Gonda
When you design a color scheme, it’s crucial to consider more than just being stylish.
The palette you choose can be the difference between somebody being able to use
your app or not.
This is the last chapter that will focus on the perceivable concept in this book. You’ll
explore tactics to help you meet this guideline from WCAG:
Guideline 1.4 Distinguishable: Make it easier for users to see and hear
content including separating foreground from background.
Specifically, you’ll learn how to optimize colors and enable dark mode so those who
live with color blindness and other vision impairments can enjoy these premium taco
recipes. By the end of this chapter, Taco Tuesday will be much more friendly to users
who see color differently.
raywenderlich.com 101
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
One way to think of it is to imagine your app under a grayscale filter. How
distinguishable would the grays be? The more different they are, the more contrast
your colors have.
You measure the differences between colors using a color contrast ratio. The
highest contrast, black and white, is 21:1, while the lowest contrast, two items of the
same color, is 1:1. Don’t worry, you don’t have to learn any tricky equations. You’ll
use tools to measure contrast.
WCAG has laid out specific contrast ratios in Success Criterion 1.4.3:
· Large Text: Large-scale text and images of large-scale text have a contrast
ratio of at least 3:1
· Incidental: Text or images of text that are part of an inactive user interface
component, that are pure decoration, that are not visible to anyone, or that are
part of a picture that contains significant other visual content, have no
contrast requirement.
Level AA
There are several details to unpack over the next several pages:
• Large text
raywenderlich.com 102
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
Search online for a color contrast calculator to run some experiments. Play with
different palettes until you find a contrast ratio close to 4.5:1. One example to try is
the color combo #767676 and #FFFFFF.
For larger text, the minimum ratio of 3.1 is lower than for the main text. Why is this?
What is considered large text?
Bigger text is easier to read, and “large” is somewhat subjective. In general, you can
follow the rule that 18sp regular text or 14sp bold text is sufficient to fall under the
guidance for “large text”.
Use your contrast checker tool to see how a 3:1 ratio looks. An example is #949494
compared to #FFFFFF.
raywenderlich.com 103
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
Now turn your attention to the elements you can exclude from these requirements —
reference the last two bullet points on Success Criterion 1.4.3. You’ll see that
incidental items are excluded. These include decorative text, disabled buttons and
hidden elements.
If you decide an element can use low-contrast colors, make sure the user has all the
information they need if they can’t see it. For example, toggle the enabled attribute
on a button so the accessibility services understand this button’s state.
Logos and brand names are also excluded. You can decide if you need to adjust them
so that they are visible.
Now that you know what this guideline means, you have the context to dig into the
vision impairments that inspired these guidelines.
When making tacos in bright conditions: Think about how hard it can be to see
your screen in the sun. High contrast ratios improve the user experience in bright
conditions.
When your device is at a distance: If you’re looking at your phone from a distance,
maybe because your hands are full of taco ingredients, you’ll comprehend more of
the content at a distance when the contrast ratios are higher.
When your glasses are MIA: Don’t forget about those who remove their glasses or
contacts before bed. If they wanted to review taco recipes while in bed, a high color
contrast means they may be able to see without those glasses or contacts.
When you live with a vision impairment: Some impairments make parts of a
person’s vision blurry or dark. Some cause floaters, while others bring double-vision.
Each impairment manifests with varying levels of severity. Higher contrast makes it
easier for many people who live with these, and other impairments, to see your taco
recipes.
raywenderlich.com 104
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
raywenderlich.com 105
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
Are you curious how it feels to live with vision impairments? Browser plugins
can help you get a glimpse into life for some of your users. The NoCoffee
Chrome Extension created the above simulations.
Try it for yourself. Search for a vision simulator for your favorite browser to
experience these changes.
Remember that these simulations won’t capture the full experience of living
with a vision impairment. The nature of the impairment, severity and length
of time a person has lived with a vision issue affects how the user interacts
with the world. Simulators simply help you put yourself in your user’s shoes so
that you can do better when making your apps accessible.
Android devices provide a way to simulate color blindness. Turn it on now by going
to Settings ▸ Developer options ▸ Simulate color space. You can find it under
Hardware accelerated rendering or just search for it.
Note: For help with the developer settings, go back to Chapter 3, “Testing &
Tools”.
raywenderlich.com 106
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
Here, you’ll find several different options. Try a couple of them to simulate color
blindness and note the color changes in different apps. Make sure you try
Monochromacy to see what your apps look like in full grayscale.
Open the project you used for the previous chapter, or get the starter project from
this chapter’s materials.
raywenderlich.com 107
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
In these suggestions, you’ll see your existing contrast, as well as the contrast needed
to meet guidelines. Use these hints to inform decisions about the palette.
If the suggestion is about a decorative text element, you can leave it alone because
it’s acceptable to inform the accessibility services to ignore it. If it’s large text and
the scanner doesn’t detect that, it’s also OK to leave it.
As you can see from the suggestions, you have some fixes to make. In a few more
paragraphs, you’ll get to make those changes.
raywenderlich.com 108
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
The Level AA guidance specifies that 4.5:1 should be the minimum text contrast.
How do you implement this guideline? You have some options:
Contrast issues are less burdensome to tackle when your app is young or undergoing
a redesign. In both cases, you have the flexibility to change the design system or
color palette, which are the most efficient ways to modify colors across an app.
For Taco Tuesday, which is a young app, you’ll change the color palette. Specifically,
you’ll change the orange accent to another orange with a higher contrast ratio to
white.
Note: How can you find more accessible colors? The most straightforward way
is to play around with different colors in a contrast checker or use an online
tool to find an alternate color similar to your existing color.
If your team has a designer, you should consult with them. What you consider
a minor change could “break” a color scheme.
raywenderlich.com 109
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
In colors.xml, replace the value for colorAccent with the suggested color. Append
the alpha value FF to the start of the hex code because some places in the app
require it:
<color name="colorAccent">#FFbf5800</color>
Build and run, then scan the same places that triggered the contrast suggestions. You
should see no more suggestions!
No suggestions.
Your new contrast for the orange accent color, #bf5800on white is 4.55:1, and the
primary green color, #006837 with white is 6.91:1.
Go to colors.xml. Change the primary color to #006635 and the accent color to
#FF983800:
<color name="colorPrimary">#006635</color>
<color name="colorAccent">#FF983800</color>
raywenderlich.com 110
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
Build and run. Depending on how well you distinguish color, you might notice that
the new accent color is much darker. It now meets the color contrast requirements
for text for Level AAA!
Level AA
raywenderlich.com 111
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
The short version of this criterion is that, if you have a view that the user needs to
perceive, understand and use, it needs a contrast ratio of at least 3:1.
app:tint="?colorOnPrimary"
raywenderlich.com 112
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
The ?colorOnPrimary value is the same white as the text uses. The reason you’re
using semantic names like “colorOnPrimary” rather than color names like “white”
will become apparent soon enough. Until then, build and run to see your changes.
While using dark mode is more commonly thought of as a style preference, for some
people, it can be the difference between being able to use an app or not.
Consider if you lived with floaters in your vision, for example. They float around,
obstructing your vision wherever they are. How frustrating that could be.
It turns out that, typically, floaters are more visible on a bright background, so
choosing a dark background improves the experience for many who live with this
condition.
raywenderlich.com 113
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
Note the values-night part of the file path, which specifies that this is for the
“night” configuration. If the project doesn’t contain the values-night directory,
create it.
These colors already meet accessibility guidelines for color contrast. The Material
theme handles all the other colors.
Theme.MaterialComponents.DayNight.NoActionBar
This DayNight theme knows how to handle dark mode for elements such as text and
backgrounds.
Finally, you need a way to turn night mode on and off. You’ll set it so that the app
follows the device’s system settings.
raywenderlich.com 114
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
Now, Taco Tuesday will use whatever theme the user has chosen.
It’s essential to provide a way to turn dark mode on and off. For some users, dark
mode makes things harder. Defaulting to the device settings is the best way to
support it.
Pure white text on a pure black background can be too harsh, especially for users
with astigmatisms, which involve deformed lenses in the eyes. A slightly softer
contrast of light text on a dark background is better for everybody.
raywenderlich.com 115
Android Accessibility by Tutorials Chapter 6: Perceivable — Colors
Key Points
• Color contrast is a comparison of lightness between two colors. It’s expressed as a
ratio, with 21:1 being the highest and 1:1 the lowest.
• A higher color contrast makes your app easier to perceive, while lower contrast
makes it more difficult.
• Level AA guidelines call for a text color ratio of 4.5:1 and a large text ratio of at
least 3:1.
• Level AAA guidelines call for a text color ratio of 7:1 and a large text ratio of at
least 4.5:1.
• Non-text elements, such as button icons, must have a ratio of at least 3:1.
• Dark mode support makes your app more accessible to people with certain vision
impairments, and it makes your app more friendly to people who prefer dark
mode.
Before moving on, you should look at the full WCAG: Perceivable (https://
www.w3.org/TR/WCAG21/#perceivable) list to get an overview of additional topics
you’ll want to study further.
When you’re done with that, please proceed full steam ahead to the next chapter!
raywenderlich.com 116
7 Chapter 7: Operable —
Navigating the Screen
By Victoria Gonda
If you’ve worked through this book chapter by chapter, then you’ve learned a lot
about what comprises a perceivable app. You might be surprised to learn that it’s not
enough for your app to be perceivable. It also needs to be operable, which is defined
by the WCAG as:
This definition means that users should be able to perform actions and navigate your
app, whether they use fingers, voice, screen readers or something else. Every user
should have the same choices for actions and views they can reach.
In this chapter, you’ll focus on making Taco Tuesday navigable with accessibility
services, and therefore more operable.
raywenderlich.com 117
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
To navigate with a keyboard, you use the Tab and Arrow keys. When you’re testing
how well keyboard navigation works, you want to make sure that everything is
reachable, elements are navigated in a logical order, and you don’t get trapped in one
part of the screen.
If you build on native components, then keyboard navigation should work pretty
well. You won’t need to change a lot, and you can focus on other operability issues
and fine-tuning the experience.
android:nextFocusForward="@+id/editText1"
You use nextFocusForward to instruct the view where to go next when the user
presses Tab or next. It says that when you’re on this view and navigate to the next
view, the view with the ID editText1 will be next.
raywenderlich.com 118
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
android:nextFocusUp="@+id/editText1"
android:nextFocusDown="@+id/editText2"
android:nextFocusLeft="@+id/editText3"
android:nextFocusRight="@+id/editText4"
These attributes tell the view where to take you when you press a directional arrow
key.
Guideline 2.4 Navigable: Provide ways to help users navigate, find content,
and determine where they are.
There’s a lot to unpack for this guideline, and this chapter can only cover so much, so
you’re going to dive right into the first use case: people who use screen readers to
discover content and determine where they are.
raywenderlich.com 119
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
Build and run. Go to your saved recipes and scan the screen with the Accessibility
Scanner. You should get this suggestion back: “Item descriptions: Multiple items
have the same description.”
You probably noticed that three views in the list items are ambiguous:
When you use a screen reader and reach one of these elements, it’s not always clear
to which recipe it pertains. A simple fix is to add the recipe name to the content
description.
raywenderlich.com 120
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
For now, you’ll just improve the checkbox and the view details button, and you’ll
save the third view for “Chapter 10, Robust”.
binding.itemRecipeMade.contentDescription =
itemView.context.getString(
R.string.try_it_description_made_recipe, recipe.name)
binding.itemRecipeDetails.contentDescription =
itemView.context.getString(
R.string.try_it_description_details_recipe, recipe.name)
Now, when you reach a recipe you’ve marked as made in the recipe list, it will say
“Made <recipe name>” instead of “Made it”. Similarly, when you reach the view
details button, the screen reader says, “<recipe name> details.”
Run the Accessibility Scanner on this view to confirm you resolved the suggestions.
Then, turn on TalkBack and observe the output when you reach these views.
raywenderlich.com 121
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
Level A
Taco Tuesday conveniently has a related bug: when you mark a recipe as made on
the list view using TalkBack, the list will lose focus. This behavior could confuse or
frustrate users when they are transported to another part of the screen (or on newer
operating systems, when the list flashes deselected).
2. Turn on TalkBack, and try to mark a recipe from the list view as made.
raywenderlich.com 122
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
1. Open TryItRecipesFragment.kt.
itemAnimator = null
This line sets the item animator to null. If you’re using adapter.notifyItem*()
when changing items, this is all you need to do.
Yes, this solution has a downside. Alternatively, you could make animations optional
so people who want animations can have them, and people using a screen reader can
skip them.
Taco Tuesday submits the full list when it changes, so there is another step: You
need to use stable IDs.
init {
setHasStableIds(true)
}
This init states that the RecyclerView uses stable IDs. Since you’re saying this, you
also need to define those IDs.
raywenderlich.com 123
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
Build and run. Use TalkBack again. When you toggle the checkbox, the focus should
stay on that item.
Managing Links
Links are common in apps, especially when displaying user-generated content.
Because of this, there are criteria for addressing links. Here’s one of them:
Success Criterion 2.4.4 Link Purpose (In Context): The purpose of each link
can be determined from the link text alone or from the link text together with
its programmatically determined link context, except where the purpose of the
link would be ambiguous to users in general.
Level A
This rule applies to links that are in line with other content.
When you make the link text understandable, you make it easier for the user to
decide if they should click it. You also allow people using screen readers to view all
the links on a page and intentionally navigate to them.
raywenderlich.com 124
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
But consider how messy links will get when people add user-generated content. It’s
much harder to control what you can’t foresee.
2. Turn on TalkBack.
4. Then either swipe up and to the right, or use press Alt + Shift + Space to open
the local context menu.
raywenderlich.com 125
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
It’s not always clear where you’ll navigate to when you open these links.
You don’t need to edit the user’s content. It’s OK to display it as-is, but you can also
make improvements.
For example, when you use it for the date “02/02/2020”, it will read “Sunday the
second of February 2020” instead of “02 slash 02 slash 2020”.
Unfortunately, not all Android devices have text-to-speech engines that use the
metadata provided by TtsSpan. You’ll add this improvement for those who have
devices supporting this feature.
Implementing TtsSpan
You’ll use TtsSpan as a custom Span for your markdown links.
Open RecipeDetailFragment.kt and find getMarkwon(), the code that lets you
customize the configuration for the markdown parser, Markwon, via plugins.
raywenderlich.com 126
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
You’ll see the below plugin that modifies the link text color — delete it:
.usePlugin(object : AbstractMarkwonPlugin() {
override fun configureTheme(builder: MarkwonTheme.Builder) {
builder.linkColor(ContextCompat.getColor(requireContext(),
R.color.colorPrimary))
}
})
Now you can replace it with a new plugin, which will still modify the link color.
Add a new, empty plugin by adding this code where you deleted the previous plugin:
.usePlugin(object : AbstractMarkwonPlugin() {
override fun configureSpansFactory(
builder: MarkwonSpansFactory.Builder
) {
super.configureSpansFactory(
builder.setFactory(Link::class.java,
object : LinkSpanFactory() {
override fun getSpans(
configuration: MarkwonConfiguration,
props: RenderProps
): Any {
}
})
)
}
})
This boilerplate code creates the AbstractMarkwonPlugin that Markwon will use
while parsing your markdown. In that anonymous class, you are overriding
configureSpansFactory() to set a custom Span factory for Link items.
An example of an acceptable return type is a list of Span items. You’ll return your
TtsSpan, a LinkSpan, so the system knows to treat it as a link, and a
ForegroundColorSpan to make sure you’re matching your theme.
raywenderlich.com 127
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
These lines get the href of the link and parse it into a Uri, so you get the different
parts of the link.
return arrayOf<Any>(
Next, add the LinkSpan and the ForegroundColorSpan to the list to preserve the
existing behavior:
LinkSpan(configuration.theme(), href,
configuration.linkResolver()),
ForegroundColorSpan(ContextCompat.getColor(requireContext(),
R.color.colorPrimary)),
Here you add a LinkSpan for link behavior. Because this is a Markwon Span, you pass
along the existing Markwon metadata. You also add a ForegroundColorSpan to
make sure the link uses your primary color.
Finally, the moment you’ve been waiting for: add your TtsSpan to the bottom of the
list and build:
TtsSpan.ElectronicBuilder()
.setPort(uri.port)
.setDomain(uri.host)
.setPath(uri.path)
.setQueryString(uri.query)
.build()
Each type that TtsSpan supports has a builder, and you use a builder to define each
part of the link. Specifically, you use the ElectronicBuilder to set the port,
domain, path, and query.
Build and run with TalkBack on. Go to the details screen for a recipe. Swipe up and to
the right to show the context menu.
When you select links, TalkBack should read the entire URL rather than just the text
displayed to sighted users.
Note: If you’re not hearing the link read aloud, your device might not have a
text-to-speech engine that consumes the metadata TtsSpan provides.
raywenderlich.com 128
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
Handling Gestures
Support for gestures gives an app a layer of polish — allowing your users to swipe or
pinch to perform actions can bring delight.
Unfortunately, you can create accessibility issues when a gesture is the only way to
perform a particular action.
Level A
Simply put, this criterion specifies that any action that you can perform using
multiple fingers or a drag of a finger must also have a single-tap-based alternative.
You might have noticed a related issue in Taco Tuesday’s recipe list: You can swipe
to discard a recipe, but swiping is the only way to discard a recipe.
You’ll implement two different options to further improve the app’s accessibility.
// 1
binding.itemRecipeTitle.setOnLongClickListener {
// 2
MaterialAlertDialogBuilder(it.context)
.setTitle(R.string.try_it_discard_confirm_title)
.setMessage(it.context.getString(
R.string.try_it_discard_confirm_message, recipe.name))
// 3
.setPositiveButton(
R.string.try_it_discard_confirm_discard) { _, _ ->
onDiscardRecipe(recipe)
}
// 4
.setNegativeButton(
raywenderlich.com 129
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
R.string.try_it_discard_confirm_cancel) { _, _ -> }
.show()
true
}
Build and run. Long press on the title of a saved recipe to see the confirmation and
delete a recipe.
Describing Actions
Now attempt the same action with TalkBack turned on. You’ll hear “Double-tap and
hold to long-press”.
class DeleteRecipeAccessibilityDelegate(
private val recipeName: String
raywenderlich.com 130
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
) : AccessibilityDelegateCompat() {
You’re also passing in a recipe name as a constructor parameter, so you can include
that name in the description.
Here you:
Finally, you need to set this accessibility delegate on the list item title.
ViewCompat.setAccessibilityDelegate(binding.itemRecipeTitle,
DeleteRecipeAccessibilityDelegate(recipe.name))
raywenderlich.com 131
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
This gives the recipe name to the accessibility delegate and sets it on the title.
Build and run. Use TalkBack again and notice that you now hear “Double-tap and
hold to discard <recipe name>.”
<ImageButton
android:id="@+id/item_recipe_discard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:iconGravity="end"
android:contentDescription="@string/shared_discard"
android:src="@drawable/ic_baseline_thumb_down_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/item_recipe_details"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/item_recipe_rating"
/>
With this, you add a thumbs-down icon to the list item that you can tap to discard
the recipe.
To finish your view’s layout, you’ll constrain the button to view the recipe that is
next to it.
app:layout_constraintStart_toEndOf="@id/item_recipe_discard"
app:layout_constraintStart_toStartOf="parent"
This constrains the icon to view the details, so it sits next to the discard icon.
raywenderlich.com 132
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
Finally, you need to set a click listener for the new icon.
binding.itemRecipeDiscard.setOnClickListener {
onDiscardRecipe(recipe)
}
This will discard the recipe when you tap the button. Build and run to ensure the new
option to discard a recipe works.
Success Criterion 2.5.5 Target Size: The size of the target for pointer inputs
is at least 44 by 44 CSS pixels…
Level AAA
Simply said: Tappable views need to be big enough. Android guidelines recommend
at least 48dp by 48dp.
raywenderlich.com 133
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
This rule, like many others, comes with some exceptions. This chapter will cover two
from the list.
If there’s another view on the screen that is sufficiently large and performs the same
action, it’s OK for the other to be too small.
Even though touch targets for links are generally smaller than 48dp by 48dp, you
don’t need to make them bigger to meet requirements when embedded in some text.
There are a couple of places where Taco Tuesday is noncompliant. Run the
Accessibility Scanner on both the discover view and the list of recipes to find them.
raywenderlich.com 134
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
android:src="@drawable/ic_baseline_thumb_down_24"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_margin="@dimen/space_normal"
android:text="No thanks"
app:icon="@drawable/ic_baseline_thumb_down_24"
app:iconPadding="@dimen/drawable_padding"
<com.google.android.material.button.MaterialButton
android:id="@+id/discover_button_discard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?colorBackgroundFloating"
android:clickable="true"
android:focusable="true"
android:contentDescription="@string/shared_discard"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_margin="@dimen/space_normal"
android:text="No thanks"
app:icon="@drawable/ic_baseline_thumb_down_24"
app:iconPadding="@dimen/drawable_padding"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/discover_button_try"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent" />
raywenderlich.com 135
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
These changes add numerous benefits and make your app more navigable:
2. There’s a little extra space around the button, making the touch targets easier to
tap and more distant from their neighbors.
Add the equivalent changes to the view with the ID discover_button_try. Your
result should look like this:
<com.google.android.material.button.MaterialButton
android:id="@+id/discover_button_try"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?colorBackgroundFloating"
android:clickable="true"
android:focusable="true"
android:contentDescription="@string/shared_try_it"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_margin="@dimen/space_normal"
android:text="Save for later"
app:icon="@drawable/ic_baseline_thumb_up_24"
app:iconPadding="@dimen/drawable_padding"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/
discover_button_discard" />
Now you have all these benefits, plus some nice style improvements, on both
buttons.
raywenderlich.com 136
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
<com.google.android.material.button.MaterialButton
android:id="@+id/item_recipe_discard"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:iconGravity="end"
android:contentDescription="@string/shared_discard"
android:textColor="?colorOnPrimary"
app:icon="@drawable/ic_baseline_thumb_down_24"
app:iconTint="?colorOnPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/item_recipe_details"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/item_recipe_rating"
/>
<com.google.android.material.button.MaterialButton
android:id="@+id/item_recipe_details"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/shared_details"
android:textColor="?colorOnPrimary"
app:icon="@drawable/ic_baseline_view_24"
app:iconTint="?colorOnPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/item_recipe_discard"
app:layout_constraintTop_toBottomOf="@id/item_recipe_rating"
/>
Now your recipe list items have buttons that meet WCAG guidelines for touch target
size! Build and run to see the changes.
raywenderlich.com 137
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
Note: Another way to make views adhere to the minimum touch target size is
to set a minimum height and width on the view or increase the padding. In
some designs, where these simple fixes don’t work, you can use a
TouchDelegate.
TouchDelegate is a helper class that lets your set the touch area for a view to
be different than the view’s bounds. You create it with a Rect for the bounds
you want to be clickable, then you assign it to the view.
Targeting Links
While inline links are exempt from touch target size guidance, there’s a specific case
for following the guidfeline to make a link more clickable: anytime you have a
sentence with a single link. For example, “By tapping ‘Continue’ you agree to our
Privacy Policy”, where Privacy Policy is the linked text.
In this scenario, you can make the full-text view tappable to increase the touch
target size.
Apply this to the “Recipe from TacoFancy” text on the details screen.
raywenderlich.com 138
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
1. Open strings.xml.
recipeDetailCreditText.setOnClickListener {
startActivity(Intent(
Intent.ACTION_VIEW,
Uri.parse("https://github.com/sinker/tacofancy")))
}
Now you have a click listener that opens the TacoFancy URL when you tap the view.
Finally, you’ll remove the LinkMovementMethod from the view since you’re no longer
using an inline link. You can decide if you want to apply a Span to keep the link
styling.
recipeDetailCreditText.movementMethod =
LinkMovementMethod.getInstance()
Build and run to ensure that tapping anywhere on the text opens the link in a
browser.
raywenderlich.com 139
Android Accessibility by Tutorials Chapter 7: Operable — Navigating the Screen
Challenges
Challenge 1: Add a unique description to the
discard button
In this chapter, you gave list item elements unique content descriptions. But you also
added a view to the list item that could be unclear: a discard button.
For this challenge, you’ll add a unique content description to this button, following
the pattern you did before. A String resource has been created to give you a starting
point: try_it_description_discard_recipe.
Try to implement this yourself, then check your results against the chapter
materials’ challenge solution.
Key Points
• Operability is a crucial part of achieving accessibility.
• Accessibility tools help you identify operability issues within an app’s navigation.
• Content descriptions for different list items should be unique so that the user can
differentiate between similar items.
• When performing operations on list items, make sure a screen reader can keep its
focus on the correct element.
• Make link text clear and descriptive, and use TtsSpan when applicable.
raywenderlich.com 140
8 Chapter 8: Operable —
Movement & Timing
By Victoria Gonda
Timed content can be impossible for some people to consume. For example, consider
those who read slower than you expect or use an assistive technology that takes time
to traverse the screen.
Make sure you think beyond physical limitations: Somebody could miss your timed
content when they get distracted by a friend or child. On top of that, some people
find time limits to be stressful. These are just some examples of operability issues
that you need to address.
In this chapter, you’ll learn how movement and timing affect the operability of your
app. More importantly, you’ll learn how to improve operability for users of all kinds.
Guideline 2.2 Enough Time: Provide users enough time to read and use
content.
raywenderlich.com 141
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
Success Criterion 2.2.1 Timing Adjustable: For each time limit that is set by
the content, at least one of the following is true:
· Turn off: The user is allowed to turn off the time limit before encountering
it; or
· Adjust: The user is allowed to adjust the time limit before encountering it
over a wide range that is at least ten times the length of the default setting; or
· Extend: The user is warned before time expires and given at least 20
seconds to extend the time limit with a simple action, for example, “press the
space bar”, and the user is allowed to extend the time limit at least ten times;
or
Level A
This criterion gives six options to consider for time limits. To summarize with two
helpful points:
2. Determining that the restriction doesn’t apply because it’s a requirement for the
function or over twenty hours.
raywenderlich.com 142
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
Open Taco Tuesday. You can pull Taco Tuesday from the starter project in the
materials for this chapter, or you can use the one you’ve been working on through
this book.
Build and run so that you can experience this timed behavior.
How would you change the behavior to conform to the guidance and success
criterion?
Turn off
• Allow the user to choose not to have a time limit before encountering it, perhaps
presenting the user an option during the onboarding flow.
• Impose no time limit by default and provide an option to opt-in to a time limit in
the settings.
Adjust
Let the user decide what length they want this time limit to be. Right now, the
default is 15 seconds. You’d need to give an option at least ten times that length,
which would be 150 seconds.
Extend
To extend, you’d need to slightly change the behavior and give the user at least 20
seconds of warning that the recipe will change. That means the default would need
to be 20 seconds or more. You’d also need to show the user a countdown and provide
a single-tap option to extend the limit.
raywenderlich.com 143
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
Real-time exception
This doesn’t apply to Taco Tuesday because the app doesn’t relate to something in
the real world, such as a limited-duration sale or a due date.
If you have an app that falls into this category, you can make it compliant by
informing the user how much time they have left.
Essential exception
Similar to the real-time exception, this scenario doesn’t apply to Taco Tuesday. It’s
relevant in time-based games where changing the timing would invalidate the game.
Maybe you could gamify Taco Tuesday to make use of this guideline!
20 Hour exception
Finally, if the time limit exceeds 20 hours, you’re in the clear. How many
milliseconds are in 20 hours?
Success Criterion 2.2.2 Pause, Stop, Hide: For moving, blinking, scrolling, or
auto-updating information, all of the following are true:
Level A
raywenderlich.com 144
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
Taco Tuesday auto-updates the content of the recipe cards. Per Success Criterion 2.2,
you need to provide a way for the user to “pause, stop, or hide it or to control the
frequency of the update.”
You’ll add a setting to allow the user to turn off the auto-advance feature. Then, in
Chapter 11, “Designing for Neurodiversity”, you’ll improve this feature further to
give an option for length of time.
To support multiple display options later, add this PreferenceCategory to the top
of the PreferenceScreen:
<PreferenceCategory app:title="@string/display_header">
</PreferenceCategory>
This creates an empty preference category with a header that signals it’s for display
purposes.
<SwitchPreferenceCompat
app:defaultValue="false"
app:key="auto_advance"
app:title="@string/preference_auto_advance_title" />
This adds a new switch preference to your settings screen. When it’s off, the recipes
won’t auto-advance, and when it’s on, they will.
Notice that you set the default to false. This is because the user currently doesn’t
have an option to turn it off before they encounter the limit, which the success
criterion specifies they should. So you turn it off for now.
Now, you need to use the value of the preference. Open DiscoverViewModel.kt.
raywenderlich.com 145
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
fetchTacoJob = viewModelScope.launch(Dispatchers.IO) {
delay(15000) // 15 seconds
fetchRandomTaco()
}
This code snippet is responsible for the 15-second auto-advance feature. Wrap it in
the following if statement:
if (sharedPreferences.getBoolean("auto_advance", false)) {
// ...
}
This checks SharedPreferences for the settings and only advances the recipe if the
user has turned on the feature.
Open app’s settings and toggle your new auto-advance setting to make sure it works
as expected. When it’s off, the recipes shouldn’t advance, and when on, they should
advance every 15 seconds.
raywenderlich.com 146
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
Managing Interruptions
Interruptions are another example of events where timing matters. You may need to
make adjustments to ensure your app is accessible. Consider the following criterion:
Level AAA
Every two minutes, you should see a pop-up dialog with a message. For another
example of this, think about the last time an app asked you for a rating or urged you
to take another action.
Dialog pop-up.
This behavior is disruptive. Consider how it works in Taco Tuesday:You’re trying to
decide whether to try a recipe. But you’re on a time limit to decide before the next
dialog shows up. Depending on the tools you use to interact with the app, you may
need to start over after the dialog shows up.
Success Criterion 2.2.4 advises you to allow the user to delay an interruption.
To make Taco Tuesday compliant, you’ll remove the interruption entirely, but you’ll
still share the information with the user. Instead of a disruptive dialog, you’ll use a
banner across the top of the screen.
raywenderlich.com 147
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
<TextView
android:id="@+id/main_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:padding="@dimen/space_normal"
android:textColor="?colorOnPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/lorem" />
This adds a full-width TextView with a background color to act as a banner. It’s in
the MainActivity, so it will display above every fragment placed in this activity.
app:layout_constraintTop_toBottomOf="@id/main_banner"
This line ensures the fragments align correctly below the banner.
app:layout_constraintTop_toTopOf="parent"
Open MainActivity.kt and find onCreate(). In this method, find the coroutine
block that starts with lifecycleScope.launch.
binding.mainBanner.text = randomMessage
raywenderlich.com 148
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
Now, you can delete the dialog. In that same place, delete the following code:
Here, you remove a property that’s no longer used; it referenced the dialog that no
longer exists.
Message banner.
Run the tests in DiscoverFragmentTest to confirm failure. For reference, the tests
are looking for a view that contains the text “Close”!
Espresso.onView(ViewMatchers.withText("Close"))
.perform(ViewActions.click())
This change removes the dialog you deleted from the test criteria.
Rerun the tests to confirm that you don’t see this error.
raywenderlich.com 149
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
Auto-dismiss
Some Android components inherently dismiss after a set amount of time. Take the
Snackbar for an example: This little view pops up on the bottom of the screen, has
an auto-dismiss option and sometimes requests the user to perform some action.
Snackbars have many baked-in accessibility features. For example, they integrate
with TalkBack. But you shouldn’t forget about them — even people who don’t use
assistive technologies and have no disabilities could easily miss a Snackbar.
When adding a Snackbar, consider if it’s acceptable for the user to miss it or fail to
react in time.
If the user must see the message or action, you need to either provide the
information another way or make the Snackbar display until the user performs a
specific action.
Animations
Always make sure the user can see that information. The obvious way to do this is to
create user controls to advance, pause, set the timing or go back.
Whatever you decide, make sure you follow WCAG guidelines so that your hard work
is enjoyable for all users.
raywenderlich.com 150
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
Since physical reactions can be life-threatening, Taco Tuesday doesn’t include any
examples to fix. Instead of an exercise, you’ll read how to reduce the risk of your
project causing negative reactions.
Eliminating Flashes
If your app includes things that flash or images that rapidly change, you may need to
comply with this criterion:
Level A
The definition for “general flash and red flash thresholds” includes specific numbers
to help you determine your app’s conformance, including guidelines related to speed,
area on the screen, luminance and color.
Level AAA
raywenderlich.com 151
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
Here are two best practices you can implement right away — people with conditions
such as vestibular disorder, aka “inner ear” disorder, will appreciate it:
Test out number two right now: Go to Accessibility Settings on your device and
look for an option to turn off animations.
Note: This might be under Text and display in your accessibility settings.
The third best practice requires you to do more learning. You need to understand
what kinds of movements are likely to trigger adverse reactions. A known trouble-
maker is parallax scrolling. With this kind of scrolling, different items move at
different speeds or directions. You can easily understand how that might cause a user
difficulty.
raywenderlich.com 152
Android Accessibility by Tutorials Chapter 8: Operable — Movement & Timing
Key Points
• Provide users with more than enough time to complete a task.
• Give users control over any time limits your app imposes.
• Make sure the user can easily control all speeds and extend any timers.
• Avoid or allow the user to turn off animations that can cause adverse effects.
Before moving onto Chapter 9, “Understandable”, take some time to investigate any
of the Operable topics (https://www.w3.org/TR/WCAG21/#operable) covered so far
that you’re interested in or might apply to your app.
raywenderlich.com 153
9 Chapter 9:
Understandable
By Victoria Gonda
Even when users can perceive and read your app, you shouldn’t assume they
understand your app. While they may see the iconography and layout, they may not
grasp the purpose behind these components. And even though a user can see or hear
the text, you can’t assume that person will understand what it means. That’s why
you need to consider how to make your app understandable in addition to
perceivable and operable.
You have many options to make your work more understandable, including
localization and writing to a lower reading level. Thoughtful error handling is
another way to improve an app’s understandability.
You’ll work through some of these options using Taco Tuesday. Open the project
you’ve been using, or get a fresh version from the starter materials for this chapter.
raywenderlich.com 154
Android Accessibility by Tutorials Chapter 9: Understandable
Increasing Readability
A substantial part of making your app understandable is making sure your content is
readable.
Here are some of the ways you can make an app more readable:
• Explaining abbreviations.
Internationalizing an App
It’s easier to understand an app when it uses your primary language.
Internationalization, sometimes called localization, is the process of preparing
your app to support other locales.
Localizing your app will make it more understandable to audiences around the
world. Depending on your market, it could be a lucrative pursuit to internationalize
your app.
raywenderlich.com 155
Android Accessibility by Tutorials Chapter 9: Understandable
Taco Tuesday mostly uses string resources, but the bottom navigation bar doesn’t.
That’s going to result in some of your text displaying in English, even if you choose
another language. You need to fix this before uploading any translations.
Open bottom_navigation_menu.xml; this is the resource where you define the text
for the bottom navigation.
These changes inform the bottom navigation to use the string resources so they can
be translated more easily. Additionally, this change improves Taco Tuesday’s
consistency — which you’ll explore more later.
android:text="View"
With:
android:text="@string/shared_details"
Now, the View button on the discover card also uses string resources.
A few other places don’t use string resources, and you’ll fix these later when you
learn about consistency.
raywenderlich.com 156
Android Accessibility by Tutorials Chapter 9: Understandable
Adding Translations
To localize Taco Tuesday, you need to add translated strings files. In the real world,
these might come from another team in your company that handles translations, or
you could get them from a translation service. Fortunately, Taco Tuesday
translations are provided for you.
Look for the translated strings.xml files in the materials for this chapter, in the
assets folder.
Note: Sometimes these language options are displayed by the system with
their translated name - so you can try Español, Português, Hrvatski, and
Nederlands.
raywenderlich.com 157
Android Accessibility by Tutorials Chapter 9: Understandable
The recipes themselves are not translated. You might recall that WCAG has different
guidelines for user-generated content. TL;DR, in most cases, you don’t need to
translate it.
Note: Some languages have lines that are much longer than the others. Now
you have another reason to support flexibility in the sizing of TextViews, in
addition to scaleability — you covered these in Chapter 4, “Perceivable —
Layout & Labeling”.
The layouts in Taco Tuesday are already using start/end attributes. However, you do
need to enable RTL in your AndroidManifest.
android:supportsRtl="true"
You can try out your app using RTL without changing your language or locale. Go to
your device’s developer options in settings and look for Force RTL layout direction.
raywenderlich.com 158
Android Accessibility by Tutorials Chapter 9: Understandable
Notice that most of the controls have flipped to the other side of the screen.
Note: You probably noticed that some text elements are still left-justified.
This is because the system is detecting the English text as a left-to-right (LTR)
language. If these strings were written in an RTL language, they would right-
justify.
Dates, for example, are formatted differently around the world. In the United States,
10/12/2020 means October 12th, 2020 but it looks like December 10th, 2020 to people
from other countries.
Most date libraries support formatting a date based on the user’s locale. For this app,
you can do this using Android’s DateFormat.
For example, add a timestamp to the error that shows when you tap “Compliment
the Chef” on the recipe detail screen.
First, add a slot for the date in the string resource. Open strings.xml and modify
shared_generic_error_message to tack on \n%s to the end of the message. Make
sure you do this for all languages.
raywenderlich.com 159
Android Accessibility by Tutorials Chapter 9: Understandable
Build and run the app. View the details for a recipe and tap “Compliment the Chef”
at the bottom of the view. You should see the message similar to the following, but
with today’s date:
You can also use other methods from DateFormat, such as getLongDateFormat(), to
get something that looks like Monday, January 3, 2000.
Similarly, you can use Currency.getInstance() to get the correct currency for a
user’s locale.
Choose to show shorter bits of text whenever you can. You can break blocks into
smaller slices, or you can hide most of the text and allow the user to expand the text
to read more. You can also edit it down to its pure essence.
In Taco Tuesday, there’s too much text on the swipeable cards on the main screen. If
you’re flipping through while starving for tacos, you’re probably only really seeing
the title.
raywenderlich.com 160
Android Accessibility by Tutorials Chapter 9: Understandable
Start by updating the image size. Open fragment_discover.xml and find the view
with the ID discover_recipe_image. Change the value of the
app:layout_constraintDimensionRatio to 2:1:
app:layout_constraintDimensionRatio="2:1"
You’ve changed the ratio of the image, and now it takes up more of the card.
Next, add some margin to the text on this card. Add the following to the view with ID
discovery_card_recipe_description:
android:layout_margin="@dimen/space_normal"
This adds some nice space between the text and the edges of the card.
android:textSize="12sp"
raywenderlich.com 161
Android Accessibility by Tutorials Chapter 9: Understandable
Now, you have a more readable font size — 9sp is too small to be readable! This
change also fixes an accessibility lint warning.
Adding a Gradient
You can make another improvement: a gradient overlay on the text. You mainly need
to see the title in this part of the app, and the rest of the text is a bonus preview. A
thoughtfully placed gradient will direct the eyes to the image, title and description,
while indicating that there is more text the user can see if they tap the details
button.
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/recipe_preview_gradient"
app:layout_constraintBottom_toBottomOf="@id/
discovery_card_recipe_description"
app:layout_constraintEnd_toEndOf="@id/
discovery_card_recipe_description"
app:layout_constraintStart_toStartOf="@id/
raywenderlich.com 162
Android Accessibility by Tutorials Chapter 9: Understandable
discovery_card_recipe_description"
app:layout_constraintTop_toTopOf="@id/
discovery_card_recipe_description" />
Build and run again. You now have a nice gradient! It looks so much more polished.
Contextualizing icons can be tricky. You can show text alongside the icon, provide a
legend someplace, include context during onboarding or add a tooltip.
In Taco Tuesday, you’ll pair text with icons. The recipe list has icons that could be
interpreted in many ways.
Ambiguous icons.
raywenderlich.com 163
Android Accessibility by Tutorials Chapter 9: Understandable
android:text="@string/shared_discard"
android:text="@string/shared_details"
app:iconGravity="end"
Now, both of the buttons have icons on the same side. That’s it! Build and run to see
your changes.
2. If you support system fonts, expect the user to change the device’s font either for
preference or to improve readability. Your app should handle this change well if
you’re correctly handling scaling text.
raywenderlich.com 164
Android Accessibility by Tutorials Chapter 9: Understandable
Level AAA
One way to comply with this criterion is to avoid words that might be hard to
understand, such as advanced words, idioms and jargon.
Idioms are phrases where the meaning of the phrase doesn’t necessarily have
anything to do with the meanings of each word on its own. For instance, using “I’m
over the moon” as an expression to mean “I’m very happy”. Unless you’re quite lucky,
you’re probably not literally going to the moon!
These words can be difficult for the user to understand or relevant to one culture but
not to another. When you can’t avoid these words, you need to define them so the
user gets the full meaning.
Intermittent message.
Many of these are fun, cringe-worthy lines. It’s sad to think that some people might
miss the meaning. They might not understand the wordplay, or it might not translate
to their native language.
What can you do in this case? You could eliminate the puns in your app, but the puns
are part of the app’s personality.
raywenderlich.com 165
Android Accessibility by Tutorials Chapter 9: Understandable
There’s no need to delete the puns; you can provide another way for the user to get
meaning. You can allow them to turn “off” the puns, or you can give them help text.
You’ll add some text alternatives to the app. When you’re done, the user can tap the
banner to read an explanation or a plainly worded version of the message.
<string-array name="pop_up_alternates">
<item>Are you enjoying the app? Rate it now in the Play Store!
</item>
<item>Victoria just tried a new recipe. What recipe are you
trying this week?</item>
<item>Jenn rated her favorite recipe 1 minute ago. Why don\'t
you help others by rating yours?</item>
<item>Ellen made tacos on Tuesday 5 weeks in a row. Beat her
streak!</item>
<item>Gabriella created her own taco recipe. Congratulate her!
</item>
<item>How are you liking this app? Let\'s talk about it. Answer
this five minute survey!</item>
<item>Let us help you find your next Taco Tuesday recipe! Swipe
right on your next find.</item>
<item>Did you find a recipe you dislike? Not your type of taco?
Leave a rating on the details screen.</item>
<item>Sorry to be all up in your grill. Do you mind taking a
second to rate the app?</item>
<item>Spectacular! You saved your first recipe. Ready to get
cooking?</item>
<item>Having issues with the app? We can talk over the phone.
Contact support now.</item>
<item>Shop for tortillas and other ingredients now so you\'re
not caught without them</item>
<item>Are you hungry? Try one of our delicious taco recipes!</
item>
<item>Have some feedback? You can tell us. We won\'t tell
anyone.</item>
<item>Try tacos on a day other than Tuesday. Tacos every day!</
item>
<item>Let\'s not waste time. You\'re our favorite customer!</
item>
<item>Take a chance on that recipe you\'re not sure about. You
might end up loving it!</item>
<item>Do you have the best taco pun? Share it with us on our
forum!</item>
<item>Taco Throw Back Thursday time! Share the best taco recipe
you\'ve ever made?</item>
<item>Ready for Taco Tuesday? How about you use one of our
tried and true recipes.</item>
</string-array>
raywenderlich.com 166
Android Accessibility by Tutorials Chapter 9: Understandable
These are the messages the user will see when they tap the banner. All of the puns
are removed.
Next, open MainActivity.kt. The bottom of onCreate() handles the logic for this
banner.
Now you can reuse this index to get the alternate text.
// 1
binding.mainBanner.setOnClickListener {
// 2
AlertDialog.Builder(this@MainActivity)
.setMessage(resources
.getStringArray(R.array.pop_up_alternates)[randomIndex])
.setPositiveButton(R.string.shared_dismiss, null)
.show()
}
Build and run. Tap on the banner to see the dialog with alternate text.
raywenderlich.com 167
Android Accessibility by Tutorials Chapter 9: Understandable
Explaining Abbreviations
Similar to difficult words or phrases, abbreviations can be a source of confusion.
Level AAA
Have you ever run across an abbreviation that you had to look up? Maybe you felt
out of touch with the hip and the young, or perhaps you felt a little foolish for having
to ask. You don’t want your users to feel that way!
The first time you use an abbreviation, you should spell the whole thing out and put
the acronym in parentheses after it. For example, consider how RTL was presented
for the first time in this chapter:
If you’re unable to explain inline, you can take a similar approach as with the lesser-
known words and give another way to uncover the meaning.
Creating Predictability
The other part of making your app understandable is making it predictable.
Guideline 3.2 Predictable: Make web pages appear and operate in predictable
ways.
When you use consistent patterns, your app becomes more comfortable to use. Users
shouldn’t need to guess what will happen when they perform an action.
raywenderlich.com 168
Android Accessibility by Tutorials Chapter 9: Understandable
Changing Context
It can be confusing when the context changes, but the user doesn’t expect it to. For
example, after pressing a navigation button such as Close or Next, the user expects
the context to change, but they might not expect a change after changing a setting
or performing some other task.
Success Criterion 3.2.2 On Input: Changing the setting of any user interface
component does not automatically cause a change of context unless the user
has been advised of the behavior before using the component.
Level A
Right now, when you check Made it on a recipe, the recipe closes. Open the app and
try this out. It’s quite unexpected!
You’ll implement the second option because it doesn’t make sense to close the view
in this case—it feels like a bug to the user.
recipeDetailMadeIt.setOnCheckedChangeListener { _, _ ->
activity?.onBackPressed()
}
This removes the OnCheckedChangeListener so that the screen doesn’t close when
the user takes this action. Build and run. Find a recipe and check the Made recipe
box. Be happy the view doesn’t close!
raywenderlich.com 169
Android Accessibility by Tutorials Chapter 9: Understandable
Navigating Consistently
Navigation patterns should be consistent throughout the app. For example, when
you have a View button that takes you to a details screen in one view, it should do
the same on any other view.
Level AA
Taco Tuesday’s navigation is already pretty consistent. Settings always takes you to
Settings. Discover leads to the same screen.
Fortunately for you, there is one thing to improve: button labels are inconsistent.
Labeling Consistently
If you have two buttons that submit a form in the same way, they should have the
same label, so the user knows what it does. This best practice applies to other kinds
of labels too.
Level AA
You’ll address the specific issue where sometimes you use the Try it and Save for
later buttons for the same action. You have a similar problem with Discard and No
thanks. You’ll correct this by changing the labels.
android:text="No thanks"
raywenderlich.com 170
Android Accessibility by Tutorials Chapter 9: Understandable
android:text="@string/shared_discard"
android:text="@string/shared_try_it"
Now, these buttons use the same language as they do in the rest of the app. And if
you change the string resource, you’ll change all the button labels at once.
Guideline 3.3 Input Assistance: Help users avoid and correct mistakes.
raywenderlich.com 171
Android Accessibility by Tutorials Chapter 9: Understandable
Level A
Taco Tuesday throws an error when you “compliment the chef” on a recipe. It’s a
hard-coded error. In your own app, this could be a network error or invalid state.
Error message.
There are already a lot of great things about this error! The message informs the user
that something went unexpectedly. It’s also contextual because it displays where the
error happened.
Now try using TalkBack on this screen. Did you hear anything about this error? No.
1. Announce it when it displays. As is, someone using a screen reader might not
know a new error exists.
2. Be more descriptive: specify what went wrong and the next steps.
One way to solve this would be to use a Toast or Snackbar to display the error. Both
components automatically work with TalkBack, which is helpful. However, these
options take the error out of context, which isn’t as helpful.
Live regions, on the other hand, keep the error message in line with the context of
the action AND make sure the screen reader announces when it displays.
raywenderlich.com 172
Android Accessibility by Tutorials Chapter 9: Understandable
recipeDetailErrorView.accessibilityLiveRegion =
ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE
Now, when the view displays, it will be announced. Build and run. Test out this
button again and see that it reads the error when it shows up.
You should explain what failed in the error message when you know the issue. In the
message, you can specify the offending action or show the message in the correct
context.
The error could be related to the user’s action, which they can resolve by repeating
the action correctly, or some issue that they can’t directly fix, like a loading error.
You should also give the user options for solving the issue. If it’s an internal server
issue, the solution could be to come back later or retry the action.
raywenderlich.com 173
Android Accessibility by Tutorials Chapter 9: Understandable
If it’s a validation error, tell them which requirement they missed in the most
straightforward language possible.
Your exercise for this section is to make the “compliment the chef” error message
actionable. You’ll ask the user to try again in a few minutes.
You don’t need to change the translations for this exercise, but you would for a
production application.
Build and run so that you can see an actionable instruction when the error displays.
Level A
It’s frustrating when you’re confused about what to enter. It’s more frustrating when
you get an ambiguous error and don’t understand why it happened.
You can use a description, hint, tooltip or something else. If a date must be in the
future when filling out a date, let the user know ahead of time and give them a
descriptive error when the input is invalid.
Imagine if the “Notes” field on a saved recipe required at least five characters to
save. You’d need to inform the user of that requirement up front. That way, users
don’t try to save notes that are too short and then curse your app when it fails to
save them.
raywenderlich.com 174
Android Accessibility by Tutorials Chapter 9: Understandable
Key Points
• Making sure your app is understandable is your responsibility.
• Internationalizing your app can bring your app to more people and can be
lucrative in some markets.
• Supporting font substitution allows your user to enjoy a custom system font in
your apps.
raywenderlich.com 175
10 Chapter 10: Robust
By Victoria Gonda
People use their devices in many different ways, so you need to make sure your app
is compatible with accessibility services.
While much of the work happens automatically or is trivial to implement, you need
to put in effort for custom views. That’s the main focus of this chapter.
A robust app is one that people can access in various ways, including with different
assistive technologies, such as screen readers.
Android does a lot of the heavy lifting by providing components with built-in
support. And it provides an interface for you to leverage. In this chapter, you’ll learn
how to use these built-in tools to improve your apps by providing more information
about views.
raywenderlich.com 176
Android Accessibility by Tutorials Chapter 10: Robust
Success Criterion 4.1.2 Name, Role, Value: For all user interface
components (including but not limited to: form elements, links and
components generated by scripts), the name and role can be programmatically
determined; states, properties, and values that can be set by the user can be
programmatically set; and notification of changes to these items is available
to user agents, including assistive technologies.
Level A
This criterion may sound daunting. And you’re not wrong. However, this chapter will
give you the insights and practice you need.
You can either work on the starter project for this chapter or continue with the
project you used earlier in the book.
In other words, if you can use a system view instead of creating a custom view, do
that! You can customize it; for example, if you need a custom button, you extend the
Button rather than starting from scratch with a View.
In Taco Tuesday, you can take advantage of a system view to improve the recipe
details screen. There’s a Made it checkbox that is currently two different views: the
label and the check box.
raywenderlich.com 177
Android Accessibility by Tutorials Chapter 10: Robust
Turn on TalkBack, run the app and observe how this view behaves with the screen
reader.
You must highlight them separately. There’s no indication that the checkbox belongs
to the “Made recipe” label.
<TextView
android:id="@+id/recipe_detail_made_it_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/recipe_detail_made_recipe" />
You’re deleting the old view because you’ll combine these views,
You also need to delete references to this label in the Kotlin code:
1. Open RecipeDetailFragment.kt.
Then, in fragment_recipe_detail.xml, add the text of the label to the CheckBox with
ID recipe_detail_made_it:
android:text="@string/recipe_detail_made_recipe"
Now, the CheckBox owns the label and can inform the accessibility services about the
associated label.
raywenderlich.com 178
Android Accessibility by Tutorials Chapter 10: Robust
Build and run. Use TalkBack again and notice that the checkbox is correctly labeled.
<string name="banner_role">banner</string>
You’ll use this in the next step. Don’t worry about translations for now.
raywenderlich.com 179
Android Accessibility by Tutorials Chapter 10: Robust
class BannerAccessibilityDelegate :
AccessibilityDelegateCompat()
1. Calling the super method so the superclass can handle its accessibility node info.
raywenderlich.com 180
Android Accessibility by Tutorials Chapter 10: Robust
Note: These actions are meant to be an example. Generally, you won’t need to
set the role.
You may need to set the role if a custom view’s role is incorrect. For example,
when you treat a non-button component like a button.
Use your new delegate: In MainActivity.kt, add this to the bottom of onCreate():
ViewCompat.setAccessibilityDelegate(
binding.mainBanner,
BannerAccessibilityDelegate()
)
Build and run. Use TalkBack to see how it announces your role.
If some of this seems familiar, remember, that you learned how to use it to add
custom actions in Chapter 7, “Operable – Navigating the Screen”.
You should review Android documentation for guidance about working on a custom
view that is actionable or has a changing state — this book does not go into that use
case.
The rest of this chapter will be a bit harder — you’ll focus on a more complicated
example.
raywenderlich.com 181
Android Accessibility by Tutorials Chapter 10: Robust
Note: Learn more about how to use an accessibility delegate at in the official
docs (https://developer.android.com/guide/topics/ui/accessibility/custom-
views#populate-events) and see what you can set on an
AccessibilityNodeInfoCompat (https://developer.android.com/reference/
androidx/core/view/accessibility/AccessibilityNodeInfoCompat).
Taco Tuesday has a custom view with multiple touch areas: CustomRatingBar, which
is the nacho and spiciness rating bars on the details screen.
Virtual views are treated as their own views from a perception and operation
standpoint. They are one means to inform accessibility services about different
touch areas.
raywenderlich.com 182
Android Accessibility by Tutorials Chapter 10: Robust
Using ExploreByTouchHelper
If you research how to create these virtual views, you’ll find many options. This
chapter will teach you how to use an ExploreByTouchHelper, a type of accessibility
delegate that can help you define touch areas.
Open CustomRatingBar.kt. Create an inner class for your touch helper delegate:
You’re using an inner class so that you can access properties and methods on the
CustomRatingBar.
This new inner class is where you’ll do much of the work to inform the accessibility
services about the state and events of the virtual views. Using only the above code,
the IDE will show a compiler error until you override the required methods.
CustomRatingBar defines the locations of these views in the rectangles list. You’ll
use this list occasionally to get information about the virtual views.
The parameter for this method is a list of virtual IDs. You add all your virtual IDs to
this list. For simplicity, this method uses the index of the views for the IDs.
raywenderlich.com 183
Android Accessibility by Tutorials Chapter 10: Robust
Next, you need to define where these views are. Add this code to
CustomRatingBarExploreByTouchHelper:
With getVirtualViewAt(), you inform the accessibility services which virtual view
was acted on at a point. By section:
2. Return the index of the ID if it’s valid. Otherwise, return INVALID_ID. One
reason for the latter to happen is that an area of your custom view is not a virtual
view.
Then, you need to share the information about the view. Add this for
onPopulateNodeForVirtualView():
node.addAction(AccessibilityNodeInfoCompat.AccessibilityActionCo
mpat.ACTION_CLICK)
// 3
node.setBoundsInParent(rectangles[virtualViewId])
}
raywenderlich.com 184
Android Accessibility by Tutorials Chapter 10: Robust
Here you have the same AccessibilityNodeInfoCompat class you used when
creating delegates before. Using that node, you:
1. Set the text of the virtual view. If the view doesn’t have text, you set this to be
identical to the content description. Remember that you’re using the index as the
ID, so the first item is index 0, the second is index 1, etc. You adjust the index
value with virtualViewId + 1 to get which rating item it is to the user.
2. Add a click action to inform the services that this item is clickable.
3. Define the bounds for this view using the saved rectangle.This is also where you
can set the state for events, a checked box or some error. Now the accessibility
services know what to read when they reach this virtual view.
Performing Actions
Finally, when someone initiates a click action, regardless of if it was with a physical
tap or through an accessibility service, you need to add logic to handle it correctly.
This view handles click actions, and because there is already a helper method for this
action, you’re:
raywenderlich.com 185
Android Accessibility by Tutorials Chapter 10: Robust
You’ve just initialized a property for your touch helper delegate and can access the
delegate in all the places you need it.
ViewCompat.setAccessibilityDelegate(this, exploreByTouchHelper)
This large chunk forwards the required methods to the accessibility delegate.
raywenderlich.com 186
Android Accessibility by Tutorials Chapter 10: Robust
Phew! You made it. Build and run. Use TalkBack to navigate through and select a
rating.
Then, append the content description in the custom rating property setter
underneath invalidate() in CustomRatingBar.kt:
contentDescription =
context.getString(R.string.current_rating_description, value)
You can further improve the experience by making sure that TalkBack announces
when the rating has changed. You learned a trick about setting the accessibility live
region in Chapter 9, “Understandable”, which you’ll use here.
accessibilityLiveRegion = ACCESSIBILITY_LIVE_REGION_POLITE
raywenderlich.com 187
Android Accessibility by Tutorials Chapter 10: Robust
Build and run. Try to change the rating using TalkBack, and listen for it to announce
the change.
There are some compat classes to help you handle different Android versions, and in
many cases, you can rely on these. They’re helpful when you’re working with APIs
that are only supported on newer versions.
Because of these constraints, you should avoid trying to make a view behave a
specific way when you’re testing. You should assume that the user is familiar with
how these services work on their device. When testing, you should focus on ensuring
you’re giving the accessibility services accurate information and creating a
consistent experience.
Android is continually evolving and improving its accessibility technology, and each
version of Android comes with a promise for new and better services. So while it is a
challenge to keep up, you can look forward to improved services with each new
release.
raywenderlich.com 188
Android Accessibility by Tutorials Chapter 10: Robust
Challenges
Challenge 1: Fix the Rating Bar
The rating bar is editable when on the details screen and not editable when in the
list view.
Hint: You don’t need the accessibility delegate if the view is not editable.
Compare your results with the challenge project in the resources for this chapter. If
you get stuck, that same project will show you the solution.
Key Points
• A robust app is one that integrates with accessibility services.
• System views are the most reliable way to support accessibility across devices.
raywenderlich.com 189
11 Chapter 11: Designing for
Neurodiversity
By Victoria Gonda
Conventional wisdom about building for accessibility focuses on visual, auditory and
motor disabilities. But another important consideration is neurodiversity.
Neurodiversity, for the sake of this discussion, is the natural variance between
people’s neurological structure and function. Brains are remarkably complex, so each
human experiences and interacts with the world in wildly different ways.
When you design an app, it’s just as important to consider users with lesser-known
syndromes, such as Williams Syndrome (a developmental disorder that can interfere
with visual and spatial reasoning), as it is to consider those who live with anxiety.
Being inclusive of these users creates a better experience, which increases their
happiness and loyalty to your product. Inclusive design also gives all of your users a
better experience.
This chapter can’t cover every experience out there — each person is unique.
However, it will give you tips to make your app more usable and enjoyable for all,
including those who live with autism, dyslexia, anxiety and ADHD.
• Provide help
• Be consistent
raywenderlich.com 190
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
• Watch phrasing
• Give alternatives
• Add configurability
Many of the solutions in this chapter will positively affect your Taco Tuesday
experience, even if you don’t identify as neurodiverse.
You’ll continue improving Taco Tuesday, so open the project you’ve been working on
or the starter project for this chapter. With that done, move on to the first topic:
Reducing time stress.
Arbitrary or unavoidable time limits make apps unusable for some people with motor
or vision disabilities. They can also induce anxiety responses. Some people need
more time to read than you might think, and time limits interfere with their ability
to comprehend and act.
WCAG wants you to avoid imposing arbitrary time limits. When you do need time
limits, allow the user to extend the time whenever possible. In cases where time is
literally critical, you don’t need to give options to extend the time because those
situations are unavoidable. Examples include a time-based game or when there’s a
physical inventory that is being quickly depleted.
When you implement timed tasks in your app, be critical and find ways to improve
the experience by giving people more time or other options.
raywenderlich.com 191
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
You added a toggle for the time limit to resolve the issue, putting the control into the
user’s hands.
There’s another option, which you’ll work with now: Make this time limit
configurable. Some users might appreciate a nudge if they haven’t made a decision.
Others will prefer more time to read and consider. Others might opt out of time
limits altogether.
You’ll add these options to Taco Tuesday. Start by adding the following to
strings.xml:
<!-- 1 -->
<string name="preference_seconds_title">Seconds for auto
advance</string>
<!-- 2 -->
<string-array name="time_options">
<item>10</item>
<item>15</item>
<item>20</item>
<item>30</item>
<item>50</item>
</string-array>
<ListPreference
android:defaultValue="15"
android:entries="@array/time_options"
android:entryValues="@array/time_options"
android:key="time_length"
android:title="@string/preference_seconds_title" />
raywenderlich.com 192
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
This code fetches the set number of seconds from preferences, defaulting to 15 if it’s
unset.
delay(seconds * 1000L)
With this call, you convert seconds to milliseconds then set the length of time before
the app auto-advances to the next recipe.
Confirm that the updated section of the method looks like this:
if (sharedPreferences.getBoolean("auto_advance", false)) {
val seconds = sharedPreferences.getString("time_length", "15")
?.toIntOrNull() ?: 15
fetchTacoTimer = viewModelScope.launch(Dispatchers.IO) {
delay(seconds * 1000L)
fetchRandomTaco()
}
}
Build and run. Confirm that you have control when auto-advance is turned on and
that you can set the interval.
raywenderlich.com 193
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
Buttons, in particular, can induce anxiety when they’re poorly explained. The user
may wonder if they get a confirmation screen after tapping “Submit” or if their card
was charged. Or if they’ll receive a barrage of spammy emails.
2. Anticipate the questions a user might ask and build the answers into the app. For
example, “Are there more steps to complete the process, or is this the last one?”
3. Assume that features and next steps are unapparent to most users.
Any clarity you can provide will reduce cognitive overhead and give your user a
smoother, more enjoyable experience.
In reality, the recipe saves when you leave the screen. This use case is an excellent
example of why you need to anticipate user questions. You’ll clarify the experience,
so the user isn’t left guessing.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/space_normal"
android:paddingBottom="@dimen/space_normal"
android:text="@string/recipe_detail_save"
android:textAppearance="@style/
TextAppearance.AppCompat.Caption" />
This logic informs the user when their changes are saved.
raywenderlich.com 194
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
Build and run. Open the first shown recipe’s details, make some changes to it, and
then observe the new message.
• Explain images
• Limit distractions
Walls of text are hard to consume. They can feel like too much to process at once or
make somebody feel burdened. Text walls are also a great reason to get distracted
with another app. And let’s face it: They’re often poorly written. In particular, long
text blocks can be stressful for people with dyslexia, autism or cognitive decline.
In Chapter 9, “Understandable”, you touched on this when you reduced the text on
the discover screen, so it’s more appropriate for the role of the view.
When you’re preparing copy for your app, opt for short sentences, short words, clear
directions and bullet points instead of paragraphs.
You can also lean into diagrams and images when there is a lot of context to share.
raywenderlich.com 195
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
Formatting Text
When you do have areas of text, format it such that:
Removing these formatting attributes makes your text easier to read, especially for
users with dyslexia.
Explaining Images
When your app has images, it’s your job to enable the user to assign meaning to
them. Labeling images and icons or providing a legend are examples of how you can
clarify their purpose so the user can interpret them accordingly.
Everyone interprets images differently. Think about all the times you’ve seen a star
icon in an app. Does the star indicate a way to rate something? Or does it favorite
something? Does it give you a badge or add something to a private list? Without an
explanation, some users will never understand this poor star’s purpose!
Each user has a different ability to assign meaning to imagery. The better you
describe these images, the clearer your app will be, and the less likely your user will
get distracted or discouraged from using your app.
raywenderlich.com 196
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
Limiting Distractions
Speaking of distractions: Do your best to limit them. Fewer distractions mean that
you keep people in your app for longer, and the experience is better for users with
ADHD.
Distractions can include a popup or something that branches off the main flow of
your app. Another example could be that the user has to close the app to adjust a
setting before using it. Distractions can become points of friction in your UX.
When building an experience, think about points of friction and if the user benefits
more from branching off to other tasks or staying focused on the task at hand.
Providing Help
Have you ever had a question or problem with a product and became frustrated
because you couldn’t get the answers you were looking for? A point of frustration is
an example of friction.
Reduce friction in your app by making help readily available, and don’t make users
jump through hoops to get answers. Hunting around for help can trigger anxiety or
discourage someone from using your app.
You can add help inline, as an FAQ, or as a help center with access to avenues like
email, chat and calls. Whatever option you implement should be easy to find and
access.
Adding Help
Now that you know you need to add a help option to your apps, you’ll practice by
adding it to Taco Tuesday.
<PreferenceScreen
android:title="@string/preference_book_forum_title">
<intent
android:action="android.intent.action.VIEW"
android:data="https://forums.raywenderlich.com/c/books/
android-accessibility-by-tutorials/74" />
</PreferenceScreen>
raywenderlich.com 197
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
This code adds an option to the settings screen that allows the user to post on a help
forum for this book.Build and run to see this change.
Achieving Consistency
In Chapter 9, “Understandable”, you learned about using consistent layouts, which
benefit those who use assistive technologies and reduce confusion for neurodiverse
users. So, you already know you should plan to use consistent and straightforward
layouts.
You want each part of your app to be as predictable as possible, with similar
elements performing similar behaviors regardless of where they’re used.
Similarly, you also want to be able to expect changes in context. Don’t change to a
different screen or context without user action unless you let them know about it
first. Otherwise, the change could confuse the user about where they are in the app
and how they got there.
When you’re careless about the words you use, your copy could be misunderstood. In
other cases, your words can negatively impact users.
raywenderlich.com 198
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
People on the autistic spectrum or who do not use English as a first language may
interpret phrases in your app literally. Read the copy in your app through a literal
filter to see if it makes sense.
And if you’re having trouble “wrapping your head around that”, maybe that’s
because skulls are rigid and aren’t meant to wrap around things. Please don’t give
yourself a concussion trying. (See what I did there?)
This includes ability. For example, don’t use terms like “crazy” or “idiotic”, as these
are derogatory words for people with disabilities. Use terms such as “outrageous” or
“misguided” instead.
These shifts in your language remove some of the ableism, and they make your
message more precise and descriptive.
Other words to avoid are more nuanced, such as “easy”, “clearly” and “just.”
Something easy or clear for one user could trigger anxiety for another. When you say
to “just” follow this instruction, you imply that it is easy for everyone.
The wrong words can be incredibly discouraging and make your user feel excluded.
Make your user feel welcome by using inclusive language.
Giving Alternatives
An underlying theme in this book is to allow users to consume your content in
multiple ways. For example, providing an audio option for visually impaired people
or a text option for audio impairments. Graphics and video can also be useful
alternatives.
Giving options also makes your app more usable for people with dyslexia.
There are more options you can provide. One example is reminders. Especially useful
for a multi-step process, prompts help the user remember content from previous
pages.
raywenderlich.com 199
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
Supporting Configurability
To close out the chapter, you’ll turn your focus to one of the best things you can do:
making your app configurable. Each user has unique needs and preferences. Some
people need light mode while others need dark. Some prefer text labels and other
logos. Some want confirmation for everything, and others prefer fewer clicks.
Adding configurability allows your app to meet the needs of more people. This gives
all your users a more tailored, and therefore enjoyable, experience.
<SwitchPreferenceCompat
app:key="dark_mode"
app:title="@string/preference_dark_mode_title"
app:useSimpleSummaryProvider="true" />
This block allows the user to set the dark mode preference on the settings screen.
findPreference<SwitchPreferenceCompat>("dark_mode")
?.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, newValue ->
AppCompatDelegate.setDefaultNightMode(
if (newValue == true) {
AppCompatDelegate.MODE_NIGHT_YES
} else {
AppCompatDelegate.MODE_NIGHT_NO
}
)
true
}
You’ve set a listener on the dark mode setting so that when the user changes the
setting on their device, it’s immediately reflected in the app’s color scheme.
raywenderlich.com 200
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
@Inject
lateinit var sharedPreferences: SharedPreferences
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
AppCompatDelegate.setDefaultNightMode(
if (sharedPreferences.getBoolean("dark_mode", false)) {
AppCompatDelegate.MODE_NIGHT_YES
} else {
AppCompatDelegate.MODE_NIGHT_NO
}
)
Now, when the app starts, the color scheme will be set according to the preferences.
Build and run. Toggle this setting and confirm that it’s working correctly.
raywenderlich.com 201
Android Accessibility by Tutorials Chapter 11: Designing for Neurodiversity
Key Points
• Being inclusive of neurodiverse users makes your app better for everyone.
• Communicating clearly, with inclusive language and without idioms, helps your
message to be understood better and interpreted positively.
• Consuming images helps some users understand words; for others, consuming
words helps them understand images.
• Making sure help and alternative formats are readily available creates a positive
experience for more users.
• Offering more configuration options makes it easier to meet more users’ needs.
You can also use the accessibility checklist found at the end of this book.
raywenderlich.com 202
12 Chapter 12: Getting Your
Team on Board
By Victoria Gonda
Now that you believe that accessibility is essential, what’s next? You know where to
start and how to improve your app’s accessibility. But how can you get buy-in from
your team to dedicate time to accessibility? How do you share what you’ve learned
and inspire your colleagues to do the same?
On many teams, accessibility is a second thought, if it’s even thought about at all. It
can be a challenge to find time to make these improvements.
The answer varies from team to team and company to company and depends on
these groups’ motivations.
In this chapter, you’ll develop a plan for your specific situation as you read. There is
no coding in this chapter, so grab a pen and paper or open a new notepad so you can
capture your ideas in real-time.
raywenderlich.com 203
Android Accessibility by Tutorials Chapter 12: Getting Your Team on Board
Recognizing a Need
Before you approach your team, you need a rough idea of your app’s accessibility and
how much attention the company pays to accessibility. If your team already has an
accessible app, you might be one of the lucky few that don’t need to budget a lot of
time to improve it.
This step doesn’t require a full audit of your app. Instead, you can do a quick pass
with an accessibility scanner and TalkBack to estimate your level of compliance.
Act: Schedule a short amount of time to skim your app for accessibility issues
using Accessibility Scanner and TalkBack. If you have limited time, commit to
a short 20-minute session to take notes and get a feel for the accessibility of
your app.
Act: Take note of who to talk to in your company to learn about existing
efforts. Make a plan for when and how to approach them. Remember that your
prime objective at this stage is to understand what’s there. You’ll construct a
strategy for inspiring the needed change later in this chapter.
Once you have an idea of the app’s compliance level, your organization’s dedication
to accessibility, and who might be interested in supporting your goals, you can start
thinking about if changes are necessary and how to set the change in motion.
Getting Buy-In
There’s a good chance that you’ve already identified a need for improvement. Now
comes the hard part: influencing that change. The first two actions you can take to
start encouraging change are:
1. Educate others.
raywenderlich.com 204
Android Accessibility by Tutorials Chapter 12: Getting Your Team on Board
You can help your team learn about this topic. You can share tips you learned in your
syncs, watch a talk on accessibility in a team meeting, or organize a book club
around this book.
Plug into how your team already learns about new topics and try to integrate it there.
Once the learning starts, there will be people on your team who are as excited about
accessibility as you.
Note: If you’re looking for a talk to watch with your team, check out ‟Increase
Your Product Quality Through Accessibility” (https://www.raywenderlich.com/
10528194-increase-your-product-quality-through-accessibility) from RW
Talks.
When you’re sharing knowledge and trying to recruit people to your cause, you need
to understand each person’s motivations. Once you know that, you can make a case
around the specific aspects of accessibility that benefit them. For example:
• If they care about user experience, show how accessibility makes a better product
for all users.
• Driving innovation.
raywenderlich.com 205
Android Accessibility by Tutorials Chapter 12: Getting Your Team on Board
Act: Who do you need to educate about accessibility on your team? What are
their goals when they make decisions? Take notes and use your thoughts to
inform a plan to help your colleagues learn how compliance can help the
product.
A final tip when you’re educating your team: The way you share information makes a
difference. Statistics can be convincing but know that data alone is not enough to
change minds. You’ll be most effective when you mix stories and data. Stories elicit
emotions, and emotions change minds and help your argument stick.
One way is to sprinkle small reminders and sustainable habits through your day.
If you get an inaccessible design, ask if you can see an alternative that accounts for
accessibility. When you’re reviewing code and see something making the app more
accessible, congratulate the author. If you learn a new accessibility tip, share it with
your team.
You can also advocate for the time in your development cycle to dedicate to
accessibility. This could look like making sure accessibility tickets are included in
each sprint or including accessibility review in QA. It’s okay to start small here. Every
little bit helps.
raywenderlich.com 206
Android Accessibility by Tutorials Chapter 12: Getting Your Team on Board
Expecting Pushback
You should expect and prepare for people to push back. People will disagree with
you. Be patient and don’t give up when someone dismisses you or casts doubt on
your ideas. Put in an effort to address your colleagues’ objections with poise.
One objection you’re likely to encounter is that spending time on accessibility will
slow the team down. This is a valid concern. You must be able to continue moving
the product forward. You can still mitigate this concern.
Review the points in Chapter 1, ‟Why Accessibility”, that show how accessibility
saves time and money over the long term. Try applying these to make a case that the
time upfront is worth it for the company.
You can always compromise on how much time to dedicate to accessibility. If you’re
initially only able to spend a little time on improving accessibility, that’s a win. Even
minor improvements will have an impact on the people they benefit.
Scaling Support
You might be wondering how you can scale your accessibility support. You need to
keep moving your product forward, even as it or your team increases in size, right?
Scaling up your support without interfering with progress is a valid concern.
You have options for how to scale up your team’s knowledge and skills. By combining
options that work well for your team, you can ease the burden and make it possible
to build out your app without exerting a disproportionate amount of energy to
support it.
In many cases, scaling will start with you. Focusing on incremental improvements
over large changes, integrating accessibility into your processes, and sharing
enthusiasm with your teammates are the keys to scaling.
raywenderlich.com 207
Android Accessibility by Tutorials Chapter 12: Getting Your Team on Board
Try to break tasks down and focus on one small bit at a time. Maybe that means you
only work with one screen or view within the screen at a time. Or, you could focus on
one criterion at a time.
The key point is that you don’t need to do it all at once. Little improvements add up
over time. Find a strategy to break down the work that works well for your team.
It’s hard to get buy-in when you’re asking people to do a lot of work or substantially
change their work habits. You’ll find that it’s much easier to get people on board
with you when what you’re asking doesn’t feel like a large, imposing change.
Act: Using the information you gathered during the rough scan of your app,
think about how to break down these chunks of work into small tasks that
would fit into your team’s workflow and processes.
If you have automation, you can also add accessibility checkpoints there. You can
make sure you have accessibility linters turned on and required to pass for new code.
Set up Espresso accessibility checks. Use the Google Play Console pre-launch reports
to uncover accessibility issues in your app.
raywenderlich.com 208
Android Accessibility by Tutorials Chapter 12: Getting Your Team on Board
Be creative about the ways you can improve your automation and processes!
Remember to get input from your team as you think through how to integrate
accessibility into your workflow. Your colleagues may surprise you with innovative
ideas you would not think of, and people are more likely to support new ways of
doing things when their ideas become a part of the solution.
Act: Take note of what processes and automation your team uses and how you
can introduce accessibility reminders and tasks. Take note of who owns or
benefits the most from current processes so that you know who is most
important to consult as you develop your plan.
Sharing Enthusiasm
When you’re the only person championing accessibility, you can get burnt out
quickly. With some teams, it can take a lot of energy to change hearts and minds.
Find the other people who are enthusiastic about accessibility and try to get them
excited before moving on to the others. It’s easier to create a culture of accessibility
when you have multiple people on your side.
One tactic that works well to build excitement comes up during code reviews — in
these rare moments, you have a captive audience and the ideal context to bring up
accessibility. Make the most of these moments by giving feedback on how well it
complies. When a teammate makes something that is accessible, praise them and tell
them why what they did was positive.
If there’s room for improvement, gently nudge them in the right direction. When you
give feedback, remember there are many aspects to making an app accessible, and
you and your teammates won’t always get it right on the first try.
Tracking Improvement
If your company relies on A/B tests or other analytics to inform decisions, someone
on your team will probably ask about user tracking.
When considering what to track, don’t even consider monitoring if a person uses
accessibility services without their knowledge. This is an invasion of privacy. Ideally,
you should never track this behavior. If you do, make sure it’s consensual.
raywenderlich.com 209
Android Accessibility by Tutorials Chapter 12: Getting Your Team on Board
Tracking this information also gives you unreliable data. Some people use
accessibility services to turn on their devices or grant permissions to apps such as
password managers. Many people would benefit from an accessible app but don’t use
accessibility services.
You can still track other indicators. Perhaps one of the most important things to
track is your legal compliance.
You can go through a company to measure this or use the Accessibility Scanner or
Espresso checks to create a system of measures for some issues.
You can also measure the types of accessibility-related support tickets. This is an
example of a qualitative measure. Do any of the tickets suggest people are trying to
use accessibility services with your app? Or are the tickets eerily devoid of such
issues? How many similar tickets are there? Review and group similar tickets and
track how many come in week over week for each type. Over time, you’ll see how
changes you make affect the user experience and identify opportunities for further
improvements. And you’ll have user-based data and insights to back you up.
Finally, you can A/B test some accessible features, but take caution with this tactic.
An unfavorable result isn’t a valid reason to move away from accessibility; adverse
results usually indicate an opportunity for improvement. Some people will even
interpret failure as proof that accessibility is a waste of time. Use the insights you
gain from the experiment to try something else. There are many paths to
compliance.
raywenderlich.com 210
Android Accessibility by Tutorials Chapter 12: Getting Your Team on Board
Key Points
• Understand your company’s approach to accessibility before taking action.
• Help your teammates understand the importance of accessibility and how to make
your app accessible.
• Track metrics and measures, but don’t invade people’s privacy by tracking who
uses accessibility services without express consent.
You’re not done yet. Working towards accessibility is a continual process. You’ll get
code or design wrong and learn something new. You’ll come across an entirely new
situation in an app to try to figure out how to make compliant. You’ll work with
someone new who you can help educate. A new accessibility service will become
available. Be patient with yourself as you go through this journey.
As you start applying your knowledge to your day-to-day work, use the headers in
this chapter to help you plan. Remember to be patient with others. You can also use
the checklist in the appendix in the back of this book to remind you what to watch
for and as a starting place for a custom checklist for your own team.
raywenderlich.com 211
13 Conclusion
What an amazing experience it’s been! You’ve learned why designing your apps with
accessibility in mind is so beneficial and how to improve the experience that users
have with your app. You’ve tried many techniques to make apps more operable,
understandable, and robust. You’ve learned how to design your app to meet the
guidelines of WCAG. Most importantly, you’ve shared the experience of your app
from your users’ perspective. And now that you understand the importance of
designing apps for accessibility, you’ve learned some great tips for bringing your
team on board and integrating accessibility into your team’s processes.
By putting the book concepts to practice, your apps will become easier to use and
understand for all users. Not only that, but you’ll rest easy knowing your app meets
the guidelines for accessibility.
We hope the ideas you saw in this book inspire you to incorporate accessibility
practices into your app and inspire your team and community to do the same!
raywenderlich.com 212
Android Accessibility by Tutorials Conclusion
If you have any questions or comments as you work through this book, please stop by
our forums at https://forums.raywenderlich.com and look for the particular forum
category for this book.
Thank you again for purchasing this book. Your continued support is what makes the
books, tutorials, videos and other things we do at raywenderlich.com possible. We
truly appreciate it!
raywenderlich.com 213
Section II: Appendix
raywenderlich.com 214
A Appendix A: Accessibility
Checklist
By Victoria Gonda
Use these checklists to remind you what to look out for in your app. You can also pick
and choose items for an audit, QA steps, or a PR checklist. While these lists don’t
cover all the guidance from WCAG, they provide a good overview of the more
common items you’ll see on Android.
Each item references the chapter in this book that covers the topic, so you can easily
find where it is in the book.
• Images and icons have content descriptions. “Chapter 2, Hello, Accessibility!” and
“Chapter 4, Perceivable — Layout & Labeling”.
• Inputs are labeled. “Chapter 4, Perceivable — Layout & Labeling” and “Chapter 9,
Understandable”.
• Instructions don’t rely on characteristics such as size, shape and color. “Chapter 5,
Perceivable — Time-Based Media & Cues”.
raywenderlich.com 215
Android Accessibility by Tutorials Appendix A: Accessibility Checklist
• Text and icons have adequate color contrast. “Chapter 6, Perceivable — Colors”.
• Touch targets are at least 48dp by 48dp. “Chapter 7, Operable — Navigating the
Screen”.
Thorough Checklist
Use this checklist when you’re doing a full audit or are trying to remember a rule.
• Images and icons have content descriptions. “Chapter 2, Hello, Accessibility!” and
“Chapter 4, Perceivable — Layout & Labeling”.
• Views are laid out logically and predictably. “Chapter 4, Perceivable — Layout &
Labeling”.
• Inputs are labeled. “Chapter 4, Perceivable — Layout & Labeling” and “Chapter 9,
Understandable”.
raywenderlich.com 216
Android Accessibility by Tutorials Appendix A: Accessibility Checklist
• Instructions don’t rely on characteristics such as size, shape and color. “Chapter 5,
Perceivable — Time-Based Media & Cues”.
• Text and icons have adequate color contrast. “Chapter 6, Perceivable — Colors”.
• Touch targets are at least 48dp by 48dp. “Chapter 7, Operable — Navigating the
Screen”.
• The language is clear. Avoid idioms and jargon, and explain abbreviations.
“Chapter 9, Understandable” and “Chapter 11, Designing for Neurodiversity”.
raywenderlich.com 217