Skip to content

Conversation

@Franklyn-R-Silva
Copy link
Contributor

Description

This PR migrates the CalendarDatePicker and _MonthPicker widgets from the deprecated SemanticsService.sendAnnouncement to a declarative approach using liveRegion: true.

As specified in #180096 and #177785, SemanticsService.sendAnnouncement is deprecated on Android as of API 36. By using a live region, we ensure that state change announcements (like month navigation and date selection) remain accessible and compliant with modern platform standards.

Changes:

  • Added _announcementText to _CalendarDatePickerState and _MonthPickerState to track accessibility messages.
  • Introduced an invisible Semantics widget with liveRegion: true in the build methods to process these announcements.
  • Updated calendar_date_picker_test.dart to verify the SemanticsFlag.isLiveRegion on the semantics tree instead of capturing imperatice announcements.

Related Issues

Fixes #177785
Relates to #180096

Tests

  • Updated packages/flutter/test/material/calendar_date_picker_test.dart to verify the new declarative announcement logic.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Dec 19, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully migrates CalendarDatePicker and _MonthPicker from the deprecated SemanticsService.sendAnnouncement to a declarative approach using Semantics with liveRegion: true. The changes are well-implemented, replacing imperative announcements with state updates that drive a live region for accessibility announcements.

My main feedback is on the test file calendar_date_picker_test.dart. While the test was correctly updated to reflect the new implementation, I found the logic for verifying semantics announcements to be brittle and contain a subtle bug. I've provided a suggestion to refactor the test for improved robustness and readability.

Overall, this is a solid improvement for accessibility compliance.

@hannah-hyj
Copy link
Member

hannah-hyj commented Dec 19, 2025

Hi @Franklyn-R-Silva,
Thank you for your attention to this a11y issue!
Not sure if you've had a chance to test this on Android yet. from the first glance, you're adding a live region outside of a SizedBox.shrink() and it will result in a zero-size node, which will cause it to be dropped from the semantics tree, and nothing will be announced.
To actually address this issue we need to wrap the semantics live region with a relevant widget and use accessiblityFocusBlockType to make sure focus traversal is still correct after adding the live region and test on an android device. Also we will only remove the a11y announcement for android but keep it on other platform.

…icker

- Wrap Semantics live region with SizedBox and Column to avoid zero-size nodes.
- Add accessiblityFocusBlockType to ensure correct focus traversal.
- Maintain imperative announcements for non-Android platforms in _handleDayChanged and _handleMonthPageChanged.
@Franklyn-R-Silva
Copy link
Contributor Author

Hi @Franklyn-R-Silva, Thank you for your attention to this a11y issue! Not sure if you've had a chance to test this on Android yet. from the first glance, you're adding a live region outside of a SizedBox.shrink() and it will result in a zero-size node, which will cause it to be dropped from the semantics tree, and nothing will be announced. To actually address this issue we need to wrap the semantics live region with a relevant widget and use accessiblityFocusBlockType to make sure focus traversal is still correct after adding the live region and test on an android device. Also we will only remove the a11y announcement for android but keep it on other platform.

Hi @hannah-hyj, thank you for the feedback!

I have updated the code to address the accessibility concerns:

Visibility: I wrapped the Semantics live regions with widgets that have physical dimensions (SizedBox and Column) to ensure they are not dropped from the semantics tree.

Focus Traversal: I added accessiblityFocusBlockType: AccessiblityFocusBlockType.none to maintain correct traversal after adding the live regions.

Platform Parity: I refactored the announcement logic to ensure Android uses the declarative approach while maintaining imperative announcements for other platforms.

Note: I am still working on updating the tests in calendar_date_picker_test.dart to reflect these changes and will push them shortly. I will ping you again once the tests are ready for review.

@Franklyn-R-Silva
Copy link
Contributor Author

Hi @Franklyn-R-Silva, Thank you for your attention to this a11y issue! Not sure if you've had a chance to test this on Android yet. from the first glance, you're adding a live region outside of a SizedBox.shrink() and it will result in a zero-size node, which will cause it to be dropped from the semantics tree, and nothing will be announced. To actually address this issue we need to wrap the semantics live region with a relevant widget and use accessiblityFocusBlockType to make sure focus traversal is still correct after adding the live region and test on an android device. Also we will only remove the a11y announcement for android but keep it on other platform.

Hi @hannah-hyj,

I’ve updated the PR to address your feedback:

Visibility: Wrapped Semantics in visible containers (SizedBox/Column) to prevent zero-size nodes.

Focus: Added accessiblityFocusBlockType to ensure correct traversal.

Platforms: Refactored logic to use declarative live regions on Android and maintain imperative announcements on other platforms.

Tests: Updated tests using the Android variant to verify the isLiveRegion flag.

Ready for another look!

@hannah-hyj hannah-hyj self-requested a review January 6, 2026 21:21
Copy link
Member

@hannah-hyj hannah-hyj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Franklyn-R-Silva I just got back from the vacation and I'm taking a look at this PR again!

Copy link
Contributor Author

@Franklyn-R-Silva Franklyn-R-Silva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

review

return Stack(
children: <Widget>[
SizedBox(height: _subHeaderHeight + scaledMaxDayPickerHeight, child: _buildPicker()),
Semantics(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should only add this Semantics widget here if platform == TargetPlatform.android.

'${_localizations.selectedDateLabel} ${widget.calendarDelegate.formatFullDate(_selectedDate!, _localizations)}$semanticLabelSuffix',
_textDirection,
);
case TargetPlatform.android:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the previous behavior was to use sendAnnouncement only on Linux, macOS, and Windows, but not on Android or iOS. I'm not sure why that was the case. However, since the goal of this PR is to remove the deprecated sendAnnouncement usage on Android, I don't think we need to change anything in this code block (L313–L328).

@hannah-hyj
Copy link
Member

Hi @Franklyn-R-Silva ! this PR looks good to me over all and i just left a few more comments!

Franklyn-R-Silva and others added 2 commits January 14, 2026 08:43
Co-authored-by: Hannah Jin <jhy03261997@gmail.com>
Co-authored-by: Hannah Jin <jhy03261997@gmail.com>
@hannah-hyj hannah-hyj added the a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) label Jan 16, 2026
@hannah-hyj
Copy link
Member

looks like some tests in calendar_date_picker_test.dart is failing, could you take a look?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove ExpansionTile usage of Semantic Announcements

2 participants