The guidance on this page expands upon the guidelines on the make apps more accessible page. Each section describes a principle that can further improve your app's accessibility.
This guidance focuses on the following best practices:
- Label elements
- Users should be able to understand the content and purpose of each interactive and meaningful UI element within your app.
- Use cues other than color
- Users should be able to clearly distinguish between categories of elements in a UI. To do so, use patterns and position, along with color, to express these differences.
- Make media content more accessible
- Try to add descriptions to your app's video or audio content so that users who consume this content don't need to rely on entirely visual or aural cues.
Label elements
It's important to provide users with useful and descriptive labels for each interactive UI element in your app. Each label should explain the meaning and purpose of a particular element. Screen readers such as TalkBack can announce these labels to users who rely on these services.
In most cases, you specify a given UI element's description in the layout
resource file that contains this element. Although you usually add labels using
the contentDescription
attribute, as explained in the guide to making apps
more accessible, there
are several other labeling techniques to keep in mind, as described in the
following sections.
Editable elements
When labeling editable elements, such as
EditText
objects, it's helpful to show
text that gives examples of valid input in the element itself, in addition to
making this example text available to screen readers. In these situations, you
can use the android:hint
attribute, as shown in the following snippet:
<!-- The hint text for en-US locale would be "Apartment, suite, or building". --> <EditText android:id="@+id/addressLine2" android:hint="@string/aptSuiteBuilding" ... />
In this situation, the View
object should have its android:labelFor
attribute set to the ID of the
EditText
element. For more details, see the section describing how to
label pairs of elements where one describes the other.
Pairs of elements where one describes the other
It's common for a given EditText
element to have a corresponding
View
object that describes the content that
users should enter within the EditText
element. On devices that run Android
4.2 (API level 17) or higher, you can indicate this relationship by setting the
View
object's android:labelFor
attribute.
An example of labeling such element pairs appears in the following snippet:
<!-- Label text for en-US locale would be "Username:" --> <TextView android:id="@+id/usernameLabel" ... android:text="@string/username" android:labelFor="@+id/usernameEntry" /> <EditText android:id="@+id/usernameEntry" ... /> <!-- Label text for en-US locale would be "Password:" --> <TextView android:id="@+id/passwordLabel" ... android:text="@string/password android:labelFor="@+id/passwordEntry" /> <EditText android:id="@+id/passwordEntry" android:inputType="textPassword" ... />
Elements in a collection
When adding labels to the elements of a collection, each label should be unique. That way, the system's accessibility services can refer to exactly one on-screen element when announcing a label. This correspondence lets users know when they've cycled through the UI or when they've moved focus to an element that they've already discovered.
In particular, you should include additional text or contextual information in
elements within reused layouts, such as
RecyclerView
objects,
so that each child element is uniquely identified.
To do so, set the content description as part of your adapter implementation, as shown in the following code snippet:
Kotlin
data class MovieRating(val title: String, val starRating: Integer) class MyMovieRatingsAdapter(private val myData: Array<MovieRating>): RecyclerView.Adapter<MyMovieRatingsAdapter.MyRatingViewHolder>() { class MyRatingViewHolder(val ratingView: ImageView) : RecyclerView.ViewHolder(ratingView) override fun onBindViewHolder(holder: MyRatingViewHolder, position: Int) { val ratingData = myData[position] holder.ratingView.contentDescription = "Movie ${position}: " + "${ratingData.title}, ${ratingData.starRating} stars" } }
Java
public class MovieRating { private String title; private int starRating; // ... public String getTitle() { return title; } public int getStarRating() { return starRating; } } public class MyMovieRatingsAdapter extends RecyclerView.Adapter<MyAdapter.MyRatingViewHolder> { private MovieRating[] myData; public static class MyRatingViewHolder extends RecyclerView.ViewHolder { public ImageView ratingView; public MyRatingViewHolder(ImageView iv) { super(iv); ratingView = iv; } } @Override public void onBindViewHolder(MyRatingViewHolder holder, int position) { MovieRating ratingData = myData[position]; holder.ratingView.setContentDescription("Movie " + position + ": " + ratingData.getTitle() + ", " + ratingData.getStarRating() + " stars") } }
Groups of related content
If your app displays several UI elements that form a natural group, such as
details of a song or attributes of a message, arrange these elements within a
container, which is usually a subclass of ViewGroup
. Set the container
object's
android:screenReaderFocusable
attribute to true
. In doing so, accessibility services can present the inner
elements' content descriptions, one after the other, in a single announcement.
This consolidation of related elements helps users of assistive technology
discover the information that's on the screen more efficiently.
The following snippet contains pieces of content that relate to one
another, so the container element, an instance of ConstraintLayout
, has its
android:screenReaderFocusable
attribute set to true
:
<!-- In response to a single user interaction, accessibility services announce both the title and the artist of the song. --> <ConstraintLayout android:id="@+id/song_data_container" ... android:screenReaderFocusable="true"> <TextView android:id="@+id/song_title" ... android:text="@string/my_song_title" /> <TextView android:id="@+id/song_artist" android:text="@string/my_songwriter" /> </ConstraintLayout>
Because accessibility services announce the inner elements' descriptions in a single utterance, it's important to keep each description as short as possible while still conveying the element's meaning.
Custom group label
If desired, you can override the platform's default grouping and ordering of a group's inner element descriptions by providing a content description for the group itself.
The following snippet shows an example of customized group description:
<!-- In response to a single user interaction, accessibility services announce the custom content description for the group. --> <ConstraintLayout android:id="@+id/song_data_container" ... android:screenReaderFocusable="true" android:contentDescription="@string/title_artist_best_song"> <TextView android:id="@+id/song_title" ... <!-- Content ignored by accessibility services --> android:text="@string/my_song_title" /> <TextView android:id="@+id/song_artist" <!-- Content ignored by accessibility services --> android:text="@string/my_songwriter" /> </ConstraintLayout>
Nested groups
If your app's interface presents multi-dimensional information, such as a
day-by-day list of festival events, use the android:screenReaderFocusable
attribute on the inner group containers. This labeling scheme provides a good
balance between number of announcements needed to discover the screen's content
and the length of each announcement.
The following code snippet shows one method of labeling groups inside of larger groups:
<!-- In response to a single user interaction, accessibility services announce the events for a single stage only. --> <ConstraintLayout android:id="@+id/festival_event_table" ... > <ConstraintLayout android:id="@+id/stage_a_event_column" android:screenReaderFocusable="true"> <!-- UI elements that describe the events on Stage A. --> </ConstraintLayout> <ConstraintLayout android:id="@+id/stage_b_event_column" android:screenReaderFocusable="true"> <!-- UI elements that describe the events on Stage B. --> </ConstraintLayout> </ConstraintLayout>
Headings within text
Some apps use headings to summarize groups of text that appear on screen. If
a particular View
element represents a heading, you can indicate its purpose
for accessibility services by setting the element's
android:accessibilityHeading
attribute to
true
.
Users of accessibility services can choose to navigate between headings instead of between paragraphs or between words. This flexibility improves the text navigation experience.
Accessibility pane titles
In Android 9 (API level 28) and higher, you can provide accessibility-friendly titles for a screen's panes. For accessibility purposes, a pane is a visually distinct portion of a window, such as the contents of a fragment. In order for accessibility services to understand a pane's window-like behavior, you should give descriptive titles to your app's panes. Accessibility services can then provide more granular information to users when a pane's appearance or content changes.
To specify the title of a pane, use the
android:accessibilityPaneTitle
attribute, as shown in the following snippet:
<!-- Accessibility services receive announcements about content changes that are scoped to either the "shopping cart view" section (top) or "browse items" section (bottom) --> <MyShoppingCartView android:id="@+id/shoppingCartContainer" android:accessibilityPaneTitle="@string/shoppingCart" ... /> <MyShoppingBrowseView android:id="@+id/browseItemsContainer" android:accessibilityPaneTitle="@string/browseProducts" ... />
Decorative elements
If an element in your UI exists only for visual spacing or visual appearance
purposes, set its
android:contentDescription
attribute to "null"
.
If your app supports only the devices that run Android 4.1 (API level 16) or
higher, you can instead set these purely decorative elements'
android:importantForAccessibility
attributes to "no"
.
Use cues other than color
To assist users with color vision deficiencies, use cues other than color to distinguish UI elements within your app's screens. These techniques could include using different shapes or sizes, providing text or visual patterns, or adding audio- or touch-based (haptic) feedback to mark the elements' differences.
Figure 1 shows two versions of an activity. One version uses only color to distinguish between two possible actions in a workflow. The other version uses the best practice of including shapes and text in addition to color to highlight the differences between the two options:
Make media content more accessible
If you're developing an app that includes media content, such as a video clip or an audio recording, try to support users with different types of accessibility needs in understanding this material. In particular, we encourage you to do the following:
- Include controls that allow users to pause or stop the media, change the volume, and toggle subtitles (captions).
- If a video presents information that is vital to completing a workflow, provide the same content in an alternative format, such as a transcript.
Additional resources
To learn more about making your app more accessible, see the following additional resources: