Accessibility is a crucial aspect of Android app development. Ensuring that your app is usable by people with disabilities not only expands your potential user base but also improves the overall user experience. TalkBack, Android’s built-in screen reader, is a primary tool used by visually impaired users to interact with their devices. In Kotlin-based XML development for Android, testing with TalkBack is essential. This post guides you through effectively testing your app using TalkBack to identify and address accessibility issues.
What is TalkBack?
TalkBack is an accessibility service on Android devices that provides spoken feedback. It allows users with visual impairments to interact with their device using touch and spoken cues, turning the content on the screen into audible speech.
Why Test with TalkBack?
- Enhanced Accessibility: Verifies that all interactive elements are accessible and navigable.
- Improved User Experience: Identifies ambiguous or poorly labeled elements, leading to a better UX for all users.
- Compliance: Helps meet accessibility guidelines and legal requirements.
- Early Detection: Catches issues early in development, saving time and resources.
Prerequisites
- An Android device or emulator.
- Android Studio installed.
- Familiarity with Kotlin and XML development for Android.
Step 1: Enable TalkBack on Your Android Device or Emulator
First, enable TalkBack on your Android device or emulator:
- On a Physical Device:
- Go to Settings > Accessibility > TalkBack.
- Toggle the TalkBack switch to ON.
- On an Emulator:
- Ensure that the emulator has Google Play Services installed.
- Navigate to Settings > Accessibility > TalkBack.
- Toggle the TalkBack switch to ON.
Once enabled, TalkBack provides spoken feedback for everything you interact with on the screen. Navigating the device becomes gesture-based.
Step 2: Basic TalkBack Navigation
Familiarize yourself with the basic TalkBack navigation gestures:
- Explore by Touch: Touch the screen to hear what’s under your finger.
- Swipe Right or Left: Move to the next or previous item on the screen.
- Double-Tap: Activate the selected item.
- Swipe Up Then Right: Access global context menu.
- Swipe Down Then Right: Access local context menu.
Step 3: Testing Your App with TalkBack
Now, run your app and navigate it using TalkBack. Pay attention to the following aspects:
1. Proper Labeling of UI Elements
Ensure all interactive elements (buttons, checkboxes, text fields, etc.) have meaningful content descriptions.
<Button
android:id="@+id/myButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Submit"
android:contentDescription="Submit form" />
val myButton: Button = findViewById(R.id.myButton)
myButton.contentDescription = "Submit the form"
Without a contentDescription, TalkBack might read the class name of the UI element or nothing at all.
2. Testing the Order of Focus
TalkBack reads elements in a specific order, typically from left to right and top to bottom. Control the focus order using android:accessibilityTraversalBefore and android:accessibilityTraversalAfter in XML, or their Kotlin equivalents.
<EditText
android:id="@+id/nameEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Name"
android:accessibilityTraversalBefore="@+id/emailEditText" />
<EditText
android:id="@+id/emailEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email" />
In this example, TalkBack will focus on the emailEditText before the nameEditText.
3. Addressing Image Descriptions
Images should always have descriptive contentDescription attributes. If an image is purely decorative, set android:importantForAccessibility="no".
<ImageView
android:id="@+id/logoImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/logo"
android:contentDescription="Company Logo" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/decorative_image"
android:importantForAccessibility="no" />
4. Handling Custom Views
If you have custom views, ensure they correctly implement accessibility APIs. Override accessibility methods and provide meaningful feedback to TalkBack.
class CustomView(context: Context, attrs: AttributeSet? = null) : View(context, attrs) {
override fun dispatchPopulateAccessibilityEvent(event: AccessibilityEvent): Boolean {
event.text.add("Custom view description")
return true
}
}
5. Testing Dynamic Content
Dynamically updating content should trigger accessibility events. Use announceForAccessibility to announce changes to the user.
val textView: TextView = findViewById(R.id.myTextView)
textView.text = "Content updated!"
textView.announceForAccessibility("Content updated!")
6. Semantic Structures in Headers and Landmarks
Proper use of semantic structure ensures a coherent flow for accessibility. Utilize heading roles for headers and landmarks for key sections. Add header roles in xml and Kotlin. Note that Roles and States are only fully exposed to accessibility services with API level 30 or higher. Make sure you are testing on at least this API level, or use a device or emulator with Android 11 or higher.
<TextView
android:id="@+id/mainTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Main Title"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
android:accessibilityHeading="true" />
val mainTitle: TextView = findViewById(R.id.mainTitle)
mainTitle.accessibilityHeading = true
Though not natively available pre API Level 30 (Android 11) accessibility live regions should also be checked to dynamically update users that new content has entered the view.
Example below of a Kotlin code block updating text in an Android application that utilizes `accessibilityLiveRegion = AccessibilityLiveRegion.POLITE` in the XML layout or programmatic equivalents using code:
This notifies accessibility services such as TalkBack when changes occur.
val updatedText : TextView = findViewById(R.id.updateTextView)
updatedText.text = "New Updates Available!"
updatedText.announceForAccessibility("New Updates Available!");
7. Managing Focus Traps and Keyboard Navigation
Make sure the user does not get stuck on a certain screen element which causes them from exiting out. Check logical navigation and clear structure by properly using ordering in your layout files, or control flow.
Step 4: Common Accessibility Issues and How to Fix Them
During testing, you might encounter several accessibility issues. Here’s how to address them:
- Missing Content Descriptions:
- Issue: TalkBack remains silent or reads the class name for unlabeled elements.
- Solution: Provide meaningful
contentDescriptionattributes for all interactive UI elements.
- Incorrect Focus Order:
- Issue: TalkBack navigates elements in an illogical order.
- Solution: Use
android:accessibilityTraversalBeforeandandroid:accessibilityTraversalAfterto define the correct focus order.
- Unclear Image Descriptions:
- Issue: Images lack descriptive content descriptions or are irrelevant to the user.
- Solution: Add descriptive
contentDescriptionattributes or setandroid:importantForAccessibility="no"for decorative images.
- Dynamic Content Updates:
- Issue: TalkBack doesn’t announce when dynamic content changes.
- Solution: Use
announceForAccessibilityto announce content updates.
Step 5: Accessibility Lint Checks and Tools
Android Studio provides accessibility lint checks that can help you identify common issues. Enable and run these checks regularly.
- Go to “Analyze” > “Inspect Code.”
- Select “Accessibility” to run specific accessibility checks.
Additionally, consider using tools like the Accessibility Scanner app from Google, which provides recommendations for improving accessibility.
Conclusion
Testing your Android app with TalkBack is crucial for ensuring accessibility. By focusing on proper labeling, logical focus order, descriptive image descriptions, dynamic content announcements, and semantic structures in your XML layouts and Kotlin code, you can create an inclusive and user-friendly experience. Regularly run accessibility lint checks and utilize available tools to catch issues early and deliver an accessible app for all users.