Unverified Commit a4de77a2 authored by Qun Cheng's avatar Qun Cheng Committed by GitHub

Remove button announcement for `MenuItemButton` and `SubmenuButton` (#127620)

parent 20637188
...@@ -42,6 +42,7 @@ abstract class ButtonStyleButton extends StatefulWidget { ...@@ -42,6 +42,7 @@ abstract class ButtonStyleButton extends StatefulWidget {
required this.autofocus, required this.autofocus,
required this.clipBehavior, required this.clipBehavior,
this.statesController, this.statesController,
this.isSemanticButton = true,
required this.child, required this.child,
}); });
...@@ -100,6 +101,15 @@ abstract class ButtonStyleButton extends StatefulWidget { ...@@ -100,6 +101,15 @@ abstract class ButtonStyleButton extends StatefulWidget {
/// {@macro flutter.material.inkwell.statesController} /// {@macro flutter.material.inkwell.statesController}
final MaterialStatesController? statesController; final MaterialStatesController? statesController;
/// Determine whether this subtree represents a button.
///
/// If this is null, the screen reader will not announce "button" when this
/// is focused. This is useful for [MenuItemButton] and [SubmenuButton] when we
/// traverse the menu system.
///
/// Defaults to true.
final bool? isSemanticButton;
/// Typically the button's label. /// Typically the button's label.
/// ///
/// {@macro flutter.widgets.ProxyWidget.child} /// {@macro flutter.widgets.ProxyWidget.child}
...@@ -425,7 +435,7 @@ class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStat ...@@ -425,7 +435,7 @@ class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStat
return Semantics( return Semantics(
container: true, container: true,
button: true, button: widget.isSemanticButton,
enabled: widget.enabled, enabled: widget.enabled,
child: _InputPadding( child: _InputPadding(
minSize: minSize, minSize: minSize,
......
...@@ -1062,6 +1062,7 @@ class _MenuItemButtonState extends State<MenuItemButton> { ...@@ -1062,6 +1062,7 @@ class _MenuItemButtonState extends State<MenuItemButton> {
style: mergedStyle, style: mergedStyle,
statesController: widget.statesController, statesController: widget.statesController,
clipBehavior: widget.clipBehavior, clipBehavior: widget.clipBehavior,
isSemanticButton: null,
child: _MenuItemLabel( child: _MenuItemLabel(
leadingIcon: widget.leadingIcon, leadingIcon: widget.leadingIcon,
shortcut: widget.shortcut, shortcut: widget.shortcut,
...@@ -1903,6 +1904,7 @@ class _SubmenuButtonState extends State<SubmenuButton> { ...@@ -1903,6 +1904,7 @@ class _SubmenuButtonState extends State<SubmenuButton> {
focusNode: _buttonFocusNode, focusNode: _buttonFocusNode,
onHover: _enabled ? (bool hovering) => handleHover(hovering, context) : null, onHover: _enabled ? (bool hovering) => handleHover(hovering, context) : null,
onPressed: _enabled ? () => toggleShowMenu(context) : null, onPressed: _enabled ? () => toggleShowMenu(context) : null,
isSemanticButton: null,
child: _MenuItemLabel( child: _MenuItemLabel(
leadingIcon: widget.leadingIcon, leadingIcon: widget.leadingIcon,
trailingIcon: widget.trailingIcon, trailingIcon: widget.trailingIcon,
......
...@@ -87,6 +87,7 @@ class TextButton extends ButtonStyleButton { ...@@ -87,6 +87,7 @@ class TextButton extends ButtonStyleButton {
super.autofocus = false, super.autofocus = false,
super.clipBehavior = Clip.none, super.clipBehavior = Clip.none,
super.statesController, super.statesController,
super.isSemanticButton,
required Widget super.child, required Widget super.child,
}); });
......
...@@ -10,6 +10,7 @@ import 'package:flutter/services.dart'; ...@@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import '../rendering/mock_canvas.dart'; import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart';
void main() { void main() {
late MenuController controller; late MenuController controller;
...@@ -3040,6 +3041,86 @@ void main() { ...@@ -3040,6 +3041,86 @@ void main() {
expect(radioValue, 1); expect(radioValue, 1);
}); });
}); });
group('Semantics', () {
testWidgets('MenuItemButton is not a semantic button', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: MenuItemButton(
style: MenuItemButton.styleFrom(fixedSize: const Size(88.0, 36.0)),
onPressed: () { },
child: const Text('ABC'),
),
),
),
);
// The flags should not have SemanticsFlag.isButton
expect(semantics, hasSemantics(
TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
actions: <SemanticsAction>[
SemanticsAction.tap,
],
label: 'ABC',
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),
transform: Matrix4.translationValues(356.0, 276.0, 0.0),
flags: <SemanticsFlag>[
SemanticsFlag.hasEnabledState,
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
textDirection: TextDirection.ltr,
),
],
),
ignoreId: true,
));
semantics.dispose();
});
testWidgets('SubMenuButton is not a semantic button', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: SubmenuButton(
onHover: (bool value) {},
style: SubmenuButton.styleFrom(fixedSize: const Size(88.0, 36.0)),
menuChildren: const <Widget>[],
child: const Text('ABC'),
),
),
),
);
// The flags should not have SemanticsFlag.isButton
expect(semantics, hasSemantics(
TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
label: 'ABC',
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),
transform: Matrix4.translationValues(356.0, 276.0, 0.0),
flags: <SemanticsFlag>[
SemanticsFlag.hasEnabledState,
],
textDirection: TextDirection.ltr,
),
],
),
ignoreId: true,
));
semantics.dispose();
});
});
} }
List<Widget> createTestMenus({ List<Widget> createTestMenus({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment