Repository navigation
Closed
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)Accessibility, e.g. VoiceOver or TalkBack. (aka a11y)customer: quake (g3)found in release: 3.24Found to occur in 3.24Found to occur in 3.24found in release: 3.27Found to occur in 3.27Found to occur in 3.27p: material_uimaterial_ui package in flutter/packagesmaterial_ui package in flutter/packagespackageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.platform-iosiOS applications specificallyiOS applications specificallyteam-iosOwned by iOS platform teamOwned by iOS platform teamtriaged-iosTriaged by iOS platform teamTriaged by iOS platform team
Description
Tracking b/325610878.
Steps to reproduce
- Enable iOS Voice Control in the settings app.
- In a Flutter app (minimal sample app below), cause a Material SnackBar widget to be displayed.
- Observe the Voice Control labels.
Expected results
There should be labels for interactive UI elements.
Actual results
There are more labels than there are interactive UI elements.
This was observed for Material2 and Material3 themes.
Code sample
Code sample
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(useMaterial3: false),
title: 'Flutter Demo',
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void displaySnackBar(BuildContext context) {
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('test bar'),
// // Enable these in order to see more numbered labels with iOS Voice Control.
// action: SnackBarAction(
// label: 'close',
// onPressed: () => print('close'),
// ),
// showCloseIcon: true,
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title, style: TextStyle(fontFamily: 'ProductSans')),
),
body: Center(
child: Text(
'test',
key: Key('CountText'),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => displaySnackBar(context),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}Screenshots or Video
Logs
Logs
[Paste your logs here]Flutter Doctor output
Doctor output
[✓] Flutter (Channel google3, on macOS 14.7 23H124 darwin-x64, locale en)
• Framework revision 3cd12f2c06 (0 days ago), 2024-10-25T00:00:00.000
• Engine revision c4b0184c87
• Dart version 3067d697ae
[✓] Android toolchain - develop for Android devices (Android SDK version Stable)
• Android SDK at google3
• Platform Stable, build-tools Stable
• Java binary at: /Applications/Android Studio with Blaze
Beta.app/Contents/jbr/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 21.0.3+-79915915-b509.11)
[✓] VS Code (version 1.94.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.86.0
[✓] Xcode - develop for iOS and macOS (Xcode 15.0)
• Xcode at /Applications/Xcode.app/Contents/Developer
[✓] Connected device (1 available)
! Error: Browsing on the local area network for CP’s iPhone (2). Ensure the
device is unlocked and attached with a cable or associated with the same
local area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code
-27)Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)Accessibility, e.g. VoiceOver or TalkBack. (aka a11y)customer: quake (g3)found in release: 3.24Found to occur in 3.24Found to occur in 3.24found in release: 3.27Found to occur in 3.27Found to occur in 3.27p: material_uimaterial_ui package in flutter/packagesmaterial_ui package in flutter/packagespackageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.platform-iosiOS applications specificallyiOS applications specificallyteam-iosOwned by iOS platform teamOwned by iOS platform teamtriaged-iosTriaged by iOS platform teamTriaged by iOS platform team
Activity
huycozy commentedon Oct 28, 2024
Reproduced this on Flutter stable and master channels.
Flutter versions (stable and master)
jmagman commentedon Oct 28, 2024
@huycozy does this reproduce on Android TalkBack?
huycozy commentedon Oct 28, 2024
@jmagman I tried finding the equivalent of iOS's Voice Control on Android TalkBack but couldn't find the exact one. I also used Accessibility Scanner app (based on one issue I tried before at #104908), I encountered #104908 that I think unrelated to this issue. Please let me know if I'm missing something and I will check the issue again on Android.
12 remaining items
meredithslota commentedon Sep 3, 2026
Following up, since the internal bug in question is our, ha.
@chunhtai -- I investigated the mechanics of this in the engine and framework (with some agentic assistance), and I think there may be a slight misunderstanding of what is causing the number to appear:
SnackBarcontent body has noonTapor tap-to-dismiss behavior. If a user actually touches the body text or uses Voice Control to say "Tap " on that badge, nothing happens (it fails silently becauseSemanticsObject.accessibilityActivatereturnsNOwhen there is nokTapaction).SemanticsObject.mm,accessibilityRespondsToUserInteractionreturnsYESwhenevernode.actions & ~kSystemActions != 0. BecauseSnackBarincludesonDismissfor the VoiceOver escape gesture, the node hasSemanticsAction::kDismiss. SincekDismissis not inkSystemActions, Flutter tells iOS that the static container responds to user interaction, prompting Voice Control to place a number badge on an un-tappable element.According to Apple's
UIAccessibility.h,accessibilityRespondsToUserInteractionis meant for elements that perform an action on touch/tap (buttons, sliders, etc.), whereaskDismissmaps exclusively toaccessibilityPerformEscape(the VoiceOver two-finger scrub / Esc key).Excluding
kDismiss(andkShowOnScreen) fromaccessibilityRespondsToUserInteractioninSemanticsObject.mmresolves the issue, I think:accessibilityPerformEscape.Does this seem reasonable?
chunhtai commentedon Sep 10, 2026
reassign to the ios team as the the fix will be in SemanticsObject.mm
LouiseHsu commentedon Oct 16, 2026
Okay, I did a little more digging into this. I think just excluding
kDismisswill not be enough to fix this.If you look at the
SnackBarwidget, it actually has 3 actions attributed to it. ItsSemanticswidget gives itkDismiss, but it actually leaks thekScrollUp/kScrollDownactions from theDismissibleit wraps. You can actually see the SnackBar assert this behaviour:So I think to fix this, we have to exclude
kDismiss,kScrollUp, andkScrollDownfromaccessibilityRespondsToUserInteraction, which should be fine because in general scrollable elements are rendered as a native UIScrollView, and shouldn't recieve a VoiceControl label, anyways.[a11y] Fixes SnackBar showing more Voice Control labels than expected (…
[a11y] Fixes SnackBar showing more Voice Control labels than expected (…
github-actions commentedon Nov 7, 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.