Repository navigation
Description
Affected platform: Android
Currently, in the AccessibilityService, the isFocusable method in AccessibilityBridge.java determines if a widget is focusable for accessibility. While this method allows widgets to become focusable based on various properties and flags, there is no direct mechanism to explicitly mark a widget as permanently unfocusable. The only workaround to make a widget unfocusable is to ensure it lacks a label, value, hint, and doesn't match any of the predefined FOCUSABLE_FLAGS. This indirect approach is limiting and doesn't provide explicit control over focusability in all scenarios.
Use Case
This feature would be particularly useful for creating more nuanced and accessible UI components, mirroring patterns found in other modern UI frameworks.
In Jetpack Compose's Material Date Picker, the <month year> portion is implemented as an unfocusable live region. The parent composable, which wraps both the <month year> text and the "Switch to selecting a year" action, is focusable. This design is intentional: when users interact with the next/previous month buttons, only the updated <month year> text is announced by screen readers, without the month/year being focusable on its own.
Here's the semantic tree structure from Jetpack Compose illustrating this:
(159133)971.View:(99, 816 - 442, 942):GRANULARITY{0}(action:FOCUS/CLEAR_A11Y_FOCUS/CLICK/SCROLL_TO_POSITION):focusable:screenReaderfocusable:clickable:accessibilityFocused
(159195)971.TextView:(131, 852 - 326, 905):TEXT{March 2025}:CONTENT{March 2025}:GRANULARITY{11}(action:A11Y_FOCUS/SCROLL_TO_POSITION):supportsTextLocation:politeLiveRegion
(159257)971.View:(347, 847 - 410, 910):CONTENT{Switch to selecting a year}:GRANULARITY{11}(action:A11Y_FOCUS/SCROLL_TO_POSITION)
You can explore a Jetpack Compose example here: https://github.com/ash2moon/jetpack-calendar
In Flutter, achieving the same component structure as in Jetpack Compose is currently challenging without resorting to semantic announcements as a workaround. The current isFocusable logic doesn't allow for explicitly marking a node as unfocusable regardless of its other semantic properties.
Here's the Flutter Date Picker example for reference: https://github.com/flutter/flutter/blob/master/examples/api/lib/material/date_picker/show_date_picker.0.dart
Semantic tree structure from Flutter:
(35607)1011.View:(152, 878 - 677, 1014):GRANULARITY{0}(action:A11Y_FOCUS):focusable
(35638)1011.View:(152, 878 - 677, 1014):CONTENT{August 2021 Select year}:GRANULARITY{0}(action:A11Y_FOCUS/CLICK/SCROLL_TO_POSITION):focusable:clickable:politeLiveRegion
Expected Behavior and Solution
Add a new semantic property, named unfocusable. When set to true for a semantic node, this property would explicitly force the node to be unfocusable by accessibility services, overriding all other conditions that might otherwise make it focusable.
-
Pros:
- Potentially more semantically aligned with the purpose of live regions, which are primarily for announcements, not direct interaction.
- Simple, easy to understand solution.
-
Cons:
- Confusion between setting
focusable = falseandunfocusable = false. Developer messages should be logged when conflicting flags are used.
- Confusion between setting
Alternative Solutions
-
Special Handling for Live Regions: Currently, live regions can still become focusable if they possess other focus-inducing properties. We could modify the system so that by default, nodes marked as live regions are implicitly unfocusable unless they are explicitly configured to be focusable through actions or other focus-related semantic properties. This would naturally address the use case outlined in the Date Picker example, where the
<month year>text is a live region intended for announcements but not direct focus.-
Pros:
- Potentially more semantically aligned with the purpose of live regions, which are primarily for announcements, not direct interaction.
- Could simplify the API and reduce the need for explicit unfocusability control in common live region scenarios.
-
Cons:
- Implicit behavior change that could surprise developers who expect live regions to be focusable in certain situations.
- May not be a general solution for all cases where unfocusability is desired for elements that are not live regions.
- Could make it more complex to intentionally make a live region focusable if needed.
-
-
New
LiveRegionWidget: Another approach is to create a dedicatedLiveRegionwidget. This widget would inherently manage the semantic properties of a live region but allow developers to provide a closure that returns the text to be announced whenever the content within theLiveRegionneeds to be updated. This widget would have an option to become focusable but by default would stay unfocusable and designed specifically for dynamic announcements.-
Pros:
- Provides a clear and declarative way for developers to create live regions within their UI.
- Encapsulates the logic of live regions within a dedicated widget, making it easier to understand and use.
- Naturally addresses the unfocusability requirement for announcement-only elements.
- Could potentially offer more control over announcement behavior and customization within the widget itself.
-
Cons:
- Complicated design and estimated work to complete this would take significantly longer than the proposed solution.
- Might be perceived as more verbose compared to simply setting an
unfocusableproperty on existing semantic nodes. - Could be less flexible if developers want to apply live region semantics to existing widgets without wrapping them in a dedicated
LiveRegionwidget.
-
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
[-]Need a new semantic property to force non-focus on widgets that have a value/label[/-][+]Add unfocusable semantic property to force non-focus on widgets[/+]chunhtai commentedon Mar 25, 2025
I think adding the a accessibilityFocusable (to differentiate SemanticsProperties.focusable which is for keyboard focus) sounds good to me.
We need to make sure we have the equivalent for iOS part though, we should not add single platform only api if possible.
cc @loic-sharma , does iOS has the equivalent for this? ie. makes a single node skip voiceover focus, but everything else like liveregion still works. The only way I am aware of is isAccessibilityElement, but that will likely disable everything.
ash2moon commentedon Mar 25, 2025
I like
accessibilityFocusabletoo. By default this could be true, but whenever it is false, the function should auto return false regardless.chunhtai commentedon Mar 25, 2025
Thinking about it more, this property may need to be tristate.
true, false, not provided.
true, false should work as expected.
When not provided, we will default to our current behavior. ie. if has label/value/hint and any non-system semantics semantic actions.
We may also need to wait for SemanticsFlag refactor from @hannah-hyj since the bit map is going to overflow if we added a tristate semantics flag like accessibilityFocusable
flutter-triage-bot commentedon Mar 25, 2025
The
fyi-accessibilitylabel is redundant with theteam-accessibilitylabel.SemanticsService.announcegets interrupted by VoiceOver #122101jmagman commentedon May 21, 2025
I checked with @hannah-hyj, this is waiting on the semantics flag refactoring to land #166101
flutter-triage-bot commentedon Sep 24, 2025
This issue is assigned to @hannah-hyj but has had no recent status updates. Please consider unassigning this issue if it is not going to be addressed in the near future. This allows people to have a clearer picture of what work is actually planned. Thanks!
hannah-hyj commentedon Sep 24, 2025
i started working on a draft PR for this #175551
github-actions commentedon Jan 1, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.