Skip to content

Use live region in error text input decorator for Android - #165531

Merged
auto-submit[bot] merged 24 commits into
flutter:masterfrom
ash2moon:feat/use-liveregion-form
May 13, 2025
Merged

auto-submit[bot] merged 24 commits into
flutter:masterfrom
ash2moon:feat/use-liveregion-form

Conversation

@ash2moon

@ash2moon ash2moon commented Mar 20, 2025 •

Copy link
Copy Markdown
Contributor

Resolves partly #165510

Context: This issue originates from #99715, where it was reported that liveRegion alone was insufficient for announcing form validation errors. While liveRegion announces the first error encountered, subsequent submissions with the same error message on Android would not trigger a re-announcement.

Original Solution: Pull request #123373 addressed this by implementing the announce event to ensure error messages were consistently announced, even for repeated submissions.

Native Android Behavior (Jetpack Compose): In native Android development using Jetpack Compose, setting the isError property of a TextField to true triggers Talkback to announce "Error invalid input." This announcement occurs only on the initial change to the error state. Subsequent errors, even if the isError property remains true, are not re-announced. This behavior closely mirrors the functionality of liveRegion, with the key difference being that liveRegion also announces the specific error text, in addition to the general error state. Testing in a native Jetpack Compose application confirms this behavior and provides a valuable comparison point against the current Flutter form example.

Suggested Action: Fork the behavior in #123373. Reinstate the use of liveRegion for error announcements within widgets/Form for Android and keep other platforms the same.

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@github-actions github-actions Bot added a: text input Entering text in a text field or keyboard related problems platform-android Android applications specifically framework flutter/packages/flutter repository. See also f: labels. engine flutter/engine related. See also e: labels. p: material_ui material_ui package in flutter/packages a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) labels Mar 20, 2025
@ash2moon ash2moon changed the title Use live region in form Use live region in error text input decorator Mar 20, 2025
@ash2moon
ash2moon requested review from a team and hannah-hyj March 20, 2025 00:02
@hannah-hyj

hannah-hyj commented Mar 20, 2025 •

Copy link
Copy Markdown
Member

The original issue #99715 is not on android but on macOS with voiceover, can you test if the live region works there?

@ash2moon

Copy link
Copy Markdown
Contributor Author

The original issue #99715 is not on android but on macOS with voiceover, can you test if the live region works there?

Looks like macos has issues with liveregion and not speaking this text. Does macos not support liveregion at all?

@ash2moon
ash2moon force-pushed the feat/use-liveregion-form branch 2 times, most recently from e58f957 to 675d730 Compare March 21, 2025 19:59
@github-actions github-actions Bot removed platform-android Android applications specifically engine flutter/engine related. See also e: labels. a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) labels Mar 21, 2025
@ash2moon
ash2moon force-pushed the feat/use-liveregion-form branch from 804b5d4 to 248d5ab Compare March 21, 2025 20:07
@ash2moon

Copy link
Copy Markdown
Contributor Author

The original issue #99715 is not on android but on macOS with voiceover, can you test if the live region works there?

I added back the original code for the other platforms and turned on liveRegion and removed the deprecated announce call for Android.

@ash2moon
ash2moon force-pushed the feat/use-liveregion-form branch from 7da36ca to 509583c Compare March 21, 2025 20:14
}

if (errorMessage.isNotEmpty) {
if (errorMessage.isNotEmpty && defaultTargetPlatform != TargetPlatform.android) {

@hannah-hyj hannah-hyj Mar 24, 2025 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can you add a comment here that android is use live region for error message and others are using announcement?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you instead refactor this into a method named "shouldPreferLiveRegionOverAnnounce"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I ended up choosing to go with isAnnounceSupported because live region would probably not be the best replacement all the time. The PR for that is in #166099

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@reidbaker this PR can be reviewed now since the parent PR was merged

@hannah-hyj hannah-hyj left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM with a nit comment

@reidbaker reidbaker left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please also update the pr description with the current state of the pr. (forked behavior instead of a pure revert)

@ash2moon see https://docs.flutter.dev/ui/adaptive-responsive/capabilities for a longer set of documenation on my thoughts behind why we should abstract the logic around platform checking to a method.

}

if (errorMessage.isNotEmpty) {
if (errorMessage.isNotEmpty && defaultTargetPlatform != TargetPlatform.android) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you instead refactor this into a method named "shouldPreferLiveRegionOverAnnounce"

Comment thread packages/flutter/test/material/text_field_test.dart Outdated
@ash2moon

Copy link
Copy Markdown
Contributor Author

Please also update the pr description with the current state of the pr. (forked behavior instead of a pure revert)

@ash2moon see https://docs.flutter.dev/ui/adaptive-responsive/capabilities for a longer set of documenation on my thoughts behind why we should abstract the logic around platform checking to a method.

Made this PR to resolve this issue:
#166099

I'll update the code in this PR once that one is merged.

@ash2moon ash2moon changed the title Use live region in error text input decorator Use live region in error text input decorator for Android Mar 31, 2025
@ash2moon
ash2moon force-pushed the feat/use-liveregion-form branch from 509583c to d2d38d9 Compare March 31, 2025 19:10
@github-actions github-actions Bot added the a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) label Mar 31, 2025
@ash2moon
ash2moon force-pushed the feat/use-liveregion-form branch 2 times, most recently from 5347271 to 20db932 Compare March 31, 2025 19:27
github-merge-queue Bot pushed a commit that referenced this pull request Apr 8, 2025
<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->

Helps unblock #165531 and is part
of #165510

*If you had to change anything in the [flutter/tests] repo, include a
link to the migration guide as per the [breaking change policy].*

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Comment thread engine/src/flutter/lib/ui/window.dart Outdated
/// announcements are generally supported without discouragement.
///
/// Use this flag to conditionally avoid making announcements on Android.
bool get noAnnounce => _kNoAnnounceIndex & _index != 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a relatively minor issue, and if you've already discussed this with others more knowledgable of a11y work feel free to disregard - but the negative qualifier no is sort of confusing (to me), at least after reading the description:

  /// Returns `false` on all other platforms (iOS, web, desktop) where such
  /// announcements are generally supported without discouragement.

I'd expect to see something like:

 /// Whether accessibility announcements (like [SemanticsService.announce])
 /// are encouraged on the current platform.
 ///
 /// Returns `false` on Android, where platform announcements are deprecated
 /// by the underlying platform.
 ///
 /// Returns `true` on all other platforms (iOS, web, desktop) where such
 /// announcements are generally supported without discouragement.
 ///
 /// Use this flag to conditionally make announcements.
bool get announce => _kAnnounceIndex & _index != 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The issue with positive notion is that for most platform it will be true. This may break exisiting embedder because this is a bit map and default value is 0.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We could rephrase it to be positive for example preferLiveRegion. That said I think we are not actually preferring live region but instead discouraging announce.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I mean a cheap option is just bool get announce => _kAnnounceIndex & _index == 0.

Anyway, just trying to get ahead of understanding:

if (!noAnnounce) { /* ... */ }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That sounds like a pretty good solution. Just gotta add some comments explaining that this is intentional and not a bug.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

How about we use _kNoAnnounceIndex for the embedder and announce for the API?

That way we can avoid confusion?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I care a lot less about the implementation detail, so SGTM

Comment thread packages/flutter/lib/src/semantics/semantics_service.dart Outdated
@ash2moon

ash2moon commented May 9, 2025

Copy link
Copy Markdown
Contributor Author

Just did my final round of testing on two real devices and made sure the media queries and announcement forking logic works well.

@auto-submit

auto-submit Bot commented May 9, 2025

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/165531, because - The status or check suite Linux linux_web_engine_tests has failed. Please fix the issues identified (or deflake) before re-applying this label.

  • The status or check suite Windows framework_tests_widgets has failed. Please fix the issues identified (or deflake) before re-applying this label.
  • The status or check suite Mac framework_tests_widgets has failed. Please fix the issues identified (or deflake) before re-applying this label.
  • The status or check suite Mac framework_tests_impeller has failed. Please fix the issues identified (or deflake) before re-applying this label.

@matanlurey

Copy link
Copy Markdown
Contributor

reason for revert: Breaks google client tests

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) a: tests "flutter test", flutter_test, or one of our tests a: text input Entering text in a text field or keyboard related problems engine flutter/engine related. See also e: labels. framework flutter/packages/flutter repository. See also f: labels. p: material_ui material_ui package in flutter/packages platform-android Android applications specifically platform-web Web applications specifically

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants