Androidforms-feedbackIntermediate

Handling Accessibility Notifications & Dynamic UI Updates

Live regions are particularly useful for conveying real-time updates, such as error messages, chat notifications, or status changes. They bridge the gap between visual updates and auditory feedback, ensuring all users receive timely information. 

Also available on:iOS

🎯 Why It Matters

Live regions ensure that dynamic content—such as error messages, chat updates, or changing status indicators—is automatically announced to users who rely on assistive technologies. Without live regions, screen reader users may completely miss important updates that happen visually on the screen. Live regions bridge this gap by providing real-time auditory feedback that keeps users informed and oriented.

💻 Implementation

Correct Code Example: Implementing Live Regions for Accessible Dynamic Updates

Demo Description

Choosing the Right Live Region Type   Selecting the right type of live region is key to providing a smooth User Experience. Use "Polite" for non-critical updates that do not need immediate attention, and "Assertive" for critical updates that should interrupt any ongoing speech.  The right type of live region is key to good User Experience. Use “Polite” for non-critical updates. Use “Assertive” for critical updates. This code snippet demonstrates how to use different types of live regions for various update scenarios: 

private fun setParagraphText() {
    val paragraph = """
        Live regions allow dynamic content updates to be communicated to screen readers.
        This demo shows how different types of live regions interact with ongoing screen reader output.
    """.trimIndent()

    paragraphTextView.text = paragraph
}

private fun setSmallParagraphText() {
    val paragraph = """
        As TalkBack reads this paragraph, you will see a weather update appear above without interrupting this ongoing screen reader output.
    """.trimIndent()

    smallParagraphTextView.text = paragraph
}

private fun startDemo() {
    weatherCard.visibility = View.GONE
    errorCard.visibility = View.GONE

    val handler = Handler(Looper.getMainLooper())

    handler.postDelayed({ showErrorMessage("Simulated error occurred") }, 12000)
    handler.postDelayed({ updateWeather() }, 18000)
}

Code Explanation

This Kotlin code simulates a sequence of updates using different live region types. When testing with TalkBack enabled, you should notice that the first paragraph text is interrupted by the error message as expected due to its assertive nature, and the weather update is announced politely after TalkBack completes reading the small paragraph text.    To thoroughly test your live regions, enable TalkBack on your device and interact with your app, paying attention to several key aspects. Focus on the timing of announcements to verify that they occur at the appropriate moments. Evaluate the clarity of the announced content to confirm it is easily understandable. Additionally, observe whether critical updates interrupt other announcements in a manner that is appropriate and not disruptive. 

Correct Code Example: Using Live Regions for Dynamic Content

Demo Description

Implementing Live Regions    Implement live regions so that updates are announced to the user automatically, instead of programmatically shifting the user’s focus. To implement a live region, we use the set Accessibility Live Region function or the android colon accessibility Live Region XML attribute.   Implement live regions so that updates are announced to the user automatically. Use set Accessibility Live Region function or; android colon accessibility Live Region XML attribute. setAccessibilityLiveRegion() android:accessibilityLiveRegionXML The following code shows how to properly use live regions for dynamic content: 

// Using live regions for dynamic content

class LiveRegionsActivity : AppCompatActivity() {

    private lateinit var weatherTextView: TextView
    private lateinit var errorTextView: TextView
    private lateinit var statusTextView: TextView

    private fun updateWeather() {
        val temperature = Random.nextInt(0, 40)
        weatherTextView.apply {
            text = "Current temperature: $temperature°C"
            accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_POLITE
        }
    }

    private fun showErrorMessage(message: String) {
        errorTextView.apply {
            text = message
            accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE
            visibility = View.VISIBLE
        }
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun updateStatus() {
        val currentTime = LocalDateTime.now()
        val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
        val formattedTime = currentTime.format(formatter)

        statusTextView.apply {
            text = "Status updated at $formattedTime"
            accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_POLITE
        }
    }
}

Code Explanation

In this demonstration, the update Weather function uses a polite live region to announce non-critical weather updates. For important error messages, the show Error Message function uses an assertive live region, ensuring they are communicated clearly and promptly. Finally, the update Status function also relies on a polite live region to provide periodic status updates without interruption. 

✅ Best Practices

Do's

  • Use live regions thoughtfully—announce only meaningful changes
  • Choose the proper region type based on urgency
  • Keep messages brief, clear, and easy to understand
  • Test with TalkBack to confirm the timing and behaviour of announcements

Don'ts

  • Announce every minor UI update
  • Use assertive regions unless absolutely necessary
  • Interrupt users' ongoing reading unnecessarily
  • Provide long or confusing announcement messages

🔍 Common Pitfalls

Overuse of assertive regions

Interrupts users too often and becomes disruptive

Announcing unnecessary updates

Leads to notification fatigue

Inconsistent messaging

Users may not understand what changed

Hidden or invisible views updating

Leads to confusing or unexpected announcements

TalkBack (Android)

Switch Access

Dynamic Type / Font Scaling

🧪 Testing Steps

  1. 1Enable TalkBack: Settings → Accessibility → TalkBack
  2. 2Trigger dynamic updates: Cause weather, error, or status updates to fire
  3. 3Observe timing: Confirm polite regions wait and assertive regions interrupt
  4. 4Assess clarity: Ensure messages are understandable and accurate
  5. 5Check repetition: Make sure updates are not announced multiple times

Become a member to read this solution, and all of Ma11y.

This resource is part of our member knowledge base. Log in or create an account to unlock:

  • Complete accessibility guidance and implementation examples
  • Curated compliance frameworks and checklists
  • Early access to new tools and features