Skip to main content

Implementing Accessibility

1. Adding Content Descriptions

Property Description Usage
android:contentDescription Provides a text description for UI elements that is read by screen readers. <ImageView<br> android:src="@drawable/icon"<br> android:contentDescription="User profile icon" />
android:accessibilityTraversalAfter Defines the traversal order for accessibility focus. <Button<br> android:text="Next"<br> android:accessibilityTraversalAfter="@id/previous_button" />

Example: Content Description for Image

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/user_icon"
    android:contentDescription="User profile image" />

Example: Content Description for Button

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Settings"
    android:contentDescription="Open settings menu" />
Note: Content descriptions should be concise and descriptive, providing meaningful context for users who rely on screen readers.

2. Using Accessibility Services

Accessibility services in Android allow applications to provide enhanced accessibility features for users with disabilities. These services can interact with the system to provide alternative ways of navigating and interacting with the UI.

Service Type Description Usage
TalkBack Screen reader that reads aloud text and describes UI elements. Enabled via system settings; provides spoken feedback for navigation.
Magnification Zooms in on parts of the screen for better visibility. Can be activated through gestures or system settings.
Switch Access Allows users to navigate through the UI using external switches. Configurable via accessibility settings for users with motor impairments.

Example: Registering an Accessibility Service

class MyAccessibilityService : AccessibilityService() {
    override fun onAccessibilityEvent(event: AccessibilityEvent) {
        // Handle accessibility events
    }

    override fun onInterrupt() {
        // Handle interruption
    }
}

Example: Declaring Accessibility Service in Manifest

<service
    android:name=".MyAccessibilityService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibility_service_config" />
</service>

Example: Accessibility Service Configuration XML

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/accessibility_service_description"
    android:packageNames="com.example.app"
    android:settingsActivity="com.example.app.AccessibilitySettings"
    android:canRetrieveWindowContent="true"
    android:canRequestTouchExplorationMode="true" />
Note: Ensure that the service is properly declared in the manifest and that it handles accessibility events efficiently to avoid performance issues.

3. Setting Accessibility Labels

Property Description Usage
android:accessibilityLabel Defines a string that describes the purpose of a view for accessibility services. <Button android:accessibilityLabel="Submit Form" ... />
android:contentDescription Alternative text for views that provides a description for accessibility services. <ImageView android:contentDescription="User profile picture" ... />

Example: Setting Accessibility Label on a Button

<Button
    android:id="@+id/submitBtn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Submit"
    android:accessibilityLabel="Click to submit the form" />

Example: Using Content Description for ImageView

<ImageView
    android:id="@+id/profileImage"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:src="@drawable/user_avatar"
    android:contentDescription="Profile picture of John Doe" />
Note: The accessibilityLabel is used for views that do not have a visible text label, while contentDescription is used for image-based views.

4. Implementing Focus Order

Property Description Usage
android:focusable Makes a view focusable <Button android:focusable="true" ... />
android:focusableInTouchMode Makes a view focusable in touch mode <EditText android:focusableInTouchMode="true" ... />
android:nextFocusForward Defines the next view to receive focus when navigating forward <Button android:nextFocusForward="@+id/next_button" ... />
android:nextFocusDown Defines the next view to receive focus when navigating down <Button android:nextFocusDown="@+id/next_down_button" ... />
android:nextFocusUp Defines the next view to receive focus when navigating up <Button android:nextFocusUp="@+id/next_up_button" ... />
android:nextFocusLeft Defines the next view to receive focus when navigating left <Button android:nextFocusLeft="@+id/next_left_button" ... />
android:nextFocusRight Defines the next view to receive focus when navigating right <Button android:nextFocusRight="@+id/next_right_button" ... />

Example: Setting Focus Order in XML

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 1"
        android:focusable="true"
        android:nextFocusDown="@+id/button2" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 2"
        android:focusable="true"
        android:nextFocusUp="@+id/button1"
        android:nextFocusDown="@+id/button3" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 3"
        android:focusable="true"
        android:nextFocusUp="@+id/button2" />

</LinearLayout>
Note: The focus order should align with the visual layout and logical flow of your app.
Warning: Avoid creating circular focus chains, as they can confuse users.

Best Practices for Focus Order

  • Ensure focus order matches visual layout
  • Use nextFocus* attributes to define custom focus flow
  • Test focus navigation using TalkBack or other accessibility tools
  • Avoid skipping views in the focus order

5. Using Heading Attributes

Attribute Description Values Notes
android:headingLevel Defines the heading level for accessibility 1, 2, ..., 6 Used to indicate hierarchy in content structure
android:accessibilityHeading Indicates that a view should be treated as a heading true, false Applies semantic meaning to views for screen readers

Example: Applying Heading Attributes

<TextView
    android:id="@+id/title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Main Title"
    android:accessibilityHeading="true"
    android:headingLevel="1" />
Note: Heading levels should follow semantic hierarchy to ensure proper navigation for users with screen readers.

6. Announcing Live Regions

Live regions allow Android apps to announce dynamic content changes to accessibility services like TalkBack. These regions notify users of updates without requiring them to navigate away from their current focus.

Property Description Values
android:accessibilityLiveRegion Defines how the system should announce changes to this view's content none, polite, assertive

Example: Setting Live Region

val textView = findViewById<TextView>(R.id.textView)
textView.setAccessibilityLiveRegion(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_TEXT)

Example: Using Polite Announcements

val statusView = findViewById<TextView>(R.id.statusView)
statusView.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_POLITE
Note: ACCESSIBILITY_LIVE_REGION_ASSERTIVE interrupts current speech, while ACCESSIBILITY_LIVE_REGION_POLITE waits for a natural pause.

7. Setting Minimum Touch Target Size

Property Value Description
android:minHeight 48dp Minimum height for touch targets
android:minWidth 48dp Minimum width for touch targets
Note: The minimum touch target size is 48dp to ensure accessibility compliance and usability across devices.

Example: Setting Touch Target Size

<Button
    android:id="@+id/myButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minWidth="48dp"
    android:minHeight="48dp"
    android:text="Click Me" />

8. Providing Text Alternatives

Property Description Usage
contentDescription Defines the text alternative for an accessibility service to read aloud <ImageView<br> android:src="@drawable/icon"<br> android:contentDescription="User profile icon" />
accessibilityLabel Used in UI components to provide a label for accessibility services val button = findViewById<Button>(R.id.button)<br>button.contentDescription = "Submit form"
accessibilityHint Provides a hint to the user about what will happen when they interact with the view val textView = findViewById<TextView>(R.id.textView)<br>textView.accessibilityHint = "Tap to view details"

Example: Using contentDescription in XML

<ImageView<br>    android:id="@+id/imageView"<br>    android:layout_width="wrap_content"<br>    android:layout_height="wrap_content"<br>    android:src="@drawable/ic_home"<br>    android:contentDescription="Home icon for navigation" />

Example: Setting contentDescription programmatically

val imageView = findViewById<ImageView>(R.id.imageView)<br>imageView.contentDescription = "User's profile picture"
Note: Always provide meaningful text alternatives for images and UI elements that do not have visible text to ensure accessibility compliance.

9. Testing with Accessibility Scanner

Example: Running Accessibility Scanner

# Install Accessibility Scanner from Google Play Store
# Or download from: https://github.com/google/Accessibility-Scanner

# Run scan on an Android device:
adb shell am start -a android.accessibilityservice.AccessibilityService

# View scan results in the app interface
Feature Description Availability
Scan Types Screen reader, touch exploration, color contrast NEW in Android 13
Scan Results Identifies accessibility issues and suggests fixes Full support in Android 12+
Integration Works with Android Studio and Firebase Test Lab BETA support
Note: Accessibility Scanner is a tool for identifying accessibility issues in Android apps. It provides real-time feedback and suggestions to improve app accessibility.
Warning: Scanner results may vary based on device settings and screen size. Always test with actual users.

Key Points

  • Accessibility Scanner helps identify accessibility issues
  • Supports real-time feedback and suggestions
  • Can be integrated with Firebase Test Lab for automated testing

10. Supporting Screen Readers

Property Description Usage
android:accessibilityHeading Marks a view as a heading for accessibility purposes <TextView android:accessibilityHeading="true" ... />
android:importantForAccessibility Controls whether a view is relevant for accessibility services <View android:importantForAccessibility="yes" ... />
android:contentDescription Provides a text description for views used by screen readers <ImageView android:contentDescription="Close button" ... />
android:labelFor Associates a label with another view for accessibility <TextView android:labelFor="@id/input_field" ... />

Example: Setting Content Description

val imageView = findViewById<ImageView>(R.id.image_view)
imageView.contentDescription = "Close button"

Example: Using Accessibility Heading

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Section Title"
    android:accessibilityHeading="true"
    />
Note: Ensure all interactive elements have descriptive content descriptions for screen readers.
Warning: Avoid using android:importantForAccessibility="no" unless necessary, as it can prevent users from accessing important UI elements.

11. Implementing Compose Accessibility

Example: Basic Compose Accessibility

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics

@Composable
fun AccessibleText() {
    Column(
        modifier = Modifier
            .semantics(mergeDescendants = true) {
                contentDescription = "Accessible text with semantic description"
            }
    ) {
        Text(text = "Hello, World!")
    }
}
Property Description Usage
contentDescription Descriptive text for accessibility services Used in semantics block to provide context for screen readers
mergeDescendants Merges semantics of child elements into parent Useful for grouping related composables under one semantic node
Note: Ensure all interactive elements have meaningful contentDescription to support users with visual impairments.

Example: Accessibility in Button

import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics

@Composable
fun AccessibleButton() {
    Button(
        onClick = { /* handle click */ },
        modifier = Modifier.semantics {
            contentDescription = "Submit form"
        }
    ) {
        Text(text = "Submit")
    }
}

Accessibility Best Practices in Jetpack Compose

  • Always provide contentDescription for non-text elements
  • Use mergeDescendants to group related composables
  • Ensure all interactive elements are accessible via screen readers
  • Test with accessibility services like TalkBack

Was this article helpful?