Sitemap
Simform Engineering

Our Engineering blog gives an inside look at our technologies from the perspective of our engineers.

Android Accessibility and TalkBack

7 min readDec 9, 2025

--

Press enter or click to view image in full size
Blog Banner

Over 1 billion people live with some form of disability. So by building a more accessible app, Android apps can serve a wider variety of users and make life easier for people with disabilities. Accessibility ensures that users with limited vision, hearing, or motor abilities can navigate and use your app without friction.

We’ll look closer at some common accessibility concepts that all developers should understand- providing appropriate labels for UI elements, ensuring proper color contrast so that users can easily read text and identify icons, and providing sufficiently large touch targets so that users can interact with the app with ease.

TalkBack

TalkBack is a gesture-based screen reader that is built into Android devices. TalkBack can be found in Settings -> Accessibility -> TalkBack -> Use TalkBack.

When TalkBack is on, the focused item on the screen is spoken out loud. TalkBack removes the assumption that the user can see, but leans into their ability to hear and touch the screen with precision. The following are the actions the user can use:

  • Swipe Right — Move to the next item
  • Swipe left — Move to the previous item
  • Double Tap — Activate an item
  • Drag finger across the screen — Focus items
  • Swipe with 2 Fingers — Scroll
  • Tap with 3 fingers — Open the TalkBack menu

Accessibility in Action

Content Description

A useful content description explains what the view does. Description needs to be both precise and concise in order to work properly with Android’s Accessibility Service. If a graphical element on the screen doesn’t have a content description, it can make user to navigate difficult in the application. TextView or its subclasses generally have text rendered, so there’s no need to provide content labels. But it’s important to provide content description for ImageViews, ImageButtons, or any view that conveys meaningful or actionable information through graphics.

Take this ImageView for example. This ImageView is a filter icon and when tapped should take the user to a new screen to filter the parkings. Since this view is associated with an action, we should indicate what the view does when it’s tapped. If an image does not contain meaningful information, we can specify it with an attribute contentDescription equals null.

<ImageView
android:id="@+id/iv_filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="Filter Parkings" />

Things to keep in mind

  • Always use localised strings; this allows a string to be translated to the user’s locale.
  • Keep labels concise; unnecessarily verbose descriptions can actually degrade the experience.
  • Don’t include the control type, such as a button. TalkBack would generally announce that on its own
  • Don’t include interaction modes. E.g., Click to Filter Parkings.
  • Don’t include state descriptions such as On or Off. State description is already built into views.
  • Views that are for decorative purposes, then one can set importantForAccessibility to no.

Hint & labelFor

EditText views should use the hint attribute to suggest the context. When we add hint attribute, then TalkBack would announce the element as Username EditText. Without hint, TalkBack would simply announce it as EditText for which user can not understand the context of this EditText.

<EditText
android:id="@+id/et_email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/email"
android:inputType="textEmailAddress"
... />

Often we use a label above the EditText, here we can use labelFor attribute to indicate the relationship. Now TalkBack will first announce the Label element and then announce the EditText below it as “EditText for Username”. This allows the user to understand what to input for the EditText field.

<!-- Label for Email Id -->
<TextView
android:id="@+id/tv_email_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/email_id"
android:labelFor="@id/et_email"
... />
<EditText
android:id="@+id/et_email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
... />
<!-- Label for Password -->
<TextView
android:id="@+id/tv_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/password"
android:labelFor="@id/et_password"
... />
<EditText
android:id="@+id/et_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPassword"
... />

Lists

Get Jay Sharma’s stories in your inbox

Join Medium for free to get updates from this writer.

For elements in lists or collections, the label should be unique so that the user will not get confused between multiple items. We can provide a unique description at runtime, like below. For e.g. — RecyclerView with Vehicle items.

override fun onBindViewHolder(holder: VehicleViewHolder, position: Int) {
val vehicle = vehicles[position]
holder.tvVehicle.contentDescription = "Vehicle ${position}: ${vehicle.nickName}"
}

Accessibility Action Labels

To modify the default behaviour or label to make it more understandable, one can replace the accessibility action’s announcement.

For e.g.: We do have an ImageView in which the user clicks to mark as favourite. By default, TalkBack would announce as “Double-tap to activate”. However, we want to announce it as “Double-tap to Favourite” so that the user can understand the purpose. We can achieve this by replacing accessibility actions like below.

ViewCompat.replaceAccessibilityAction(
targetView, // View to target
AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
getText(R.string.favorite), // Custom action
null
)

Custom State Description

Some Android Widgets, like CheckBox & Switch contain states that they expose to the Accessibility Service. For e.g. CheckBox has two states announced by TalkBack as “Checked” and “Not Checked”. Similarly, “On” & “Off” for the Switch. It is possible to customise these state descriptions to improve user experience.

ViewCompat.setAccessibilityDelegate(targetView, object : AccessibilityDelegateCompat() {
override fun onInitializeAccessibilityNodeInfo(
host: View,
info: AccessibilityNodeInfoCompat
) {
super.onInitializeAccessibilityNodeInfo(host, info)
info.addAction(
AccessibilityNodeInfoCompat.AccessibilityActionCompat(
AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK.id,
if (targetView.isChecked) {
"Turn off app notifications"
}
else {
"Turn on app notifications"
}
)
)
}
})

This Switch will now announce its standard click action as "Double-tap to Turn on app notifications" if unchecked and "Double-tap to Turn off app notifications" if checked.

Useful Attributes

We can use the attributes like android:accessibilityTraversalBefore and android:accessibilityTraversalAfter to control accessibility focus order, if and only if it is essential to do so; otherwise, by using the correct layout sequence and structure to set accessibility focus order.

To group content, enclose all the relevant content elements in a single layout ViewGroup and set android:importantForAccessibility=”yes” & android:focusable=”true” on that ViewGroup. These properties make the ViewGroup focusable by a screen reader and tell the screen reader to combine all child element text into a single announcement.

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAccessibility="yes"
android:focusable="true"
app:layout_constraintTop_toTopOf="parent">

<TextView
android:id="@+id/tv_movie_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginStart="25dp"
android:textSize="30sp"
android:text="Avatar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/tv_movie_des"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginStart="25dp"
android:accessibilityTraversalAfter="@id/tv_movie_name"
android:textSize="20sp"
android:text="Avatar is a 2009 epic science fiction film written and directed by James Cameron."
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_movie_name" />
</androidx.constraintlayout.widget.ConstraintLayout>

Contrast

When background and foreground colors of UI elements have insufficient contrast, text can be hard to read, and icons can be hard to distinguish. Proper color contrast helps users with visual impairments more easily.

Large text, considered anything above 18dp or larger or 14dp and larger when bold, should have a 3-to-1 ratio.

Web tools like contrast checker can be used to test or ensure the color contrast is sufficient. Or one can use the Problems window in Android Studio for layout validation, which provides a warning and suggestion to improve for views that have insufficient text color contrast ratio.

Press enter or click to view image in full size
A screenshot of Problem Panel window in Android Studio which highlights the Insufficient text color contrast ration
Problems window

Touch Target

Touch targets of elements should be at least 48dp by 48dp (larger is even better) so that reliable interaction can happen. There are several techniques for achieving an appropriate touch target size, such as we can set the width or height to 48dp if the content/drawable is that size or smaller. Or we can add padding to ensure the minimum target size. Setting android:minWidth and android:minHeight to 48dp is by far the preferred method, and applies well to other touchable elements. In the latest Android Studio, the Problem Panel will also flag the touch target, and we can resolve those specific warnings by ensuring the minimum recommended touch target for touchable elements.

<ImageButton
android:id="@+id/iv_filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="12dp"
android:src="@drawable/ic_angle_right_outline"
android:contentDescription="Next" />
<!-- icon is of 24dpX24dp -->
<!-- 12dp of padding will expand the button appropriately to recommended size. -->

Accessibility Scanner App

Accessibility Scanner is a tool that can help us with accessibility testing. Scanner scans the screen and provides suggestions on how to improve the accessibility of your app using the accessibility test framework under the hood. It provides specific suggestions after looking at features such as content labels, touch target size, clickable items, and color contrast for text and icons.

Press enter or click to view image in full size
A screenshot of Accessibility Scanner app in Play Store
App in the Play Store

How to use Accessibility Scanner:

  • Open the app and follow the prompts to turn on the Accessibility Scanner Service.
  • Navigate to the app you wish to scan and tap the floating button.
  • Choose to perform a single scan or record an entire user journey across multiple screens.

Example:

Press enter or click to view image in full size
Multiple screenshots of an application which is demonstrating the use of Accessibility Scanner app by Google
An example showcasing the use of Accessibility Scanner

Conclusion

In this guide, we learnt how we can build the apps that everyone can use with the help of the tools provided by Android. Ensuring proper content descriptions, comfortable touch targets, and readable color contrast are simple steps to make our App more accessible and respect every user’s needs.

--

Simform Engineering
Simform Engineering

Published in Simform Engineering

Our Engineering blog gives an inside look at our technologies from the perspective of our engineers.