mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
Added enableFeedback property PopupMenuButton (#69890)
This commit is contained in:
parent
7b40272e10
commit
d2f06f6f05
|
@ -945,6 +945,7 @@ class PopupMenuButton<T> extends StatefulWidget {
|
|||
this.enabled = true,
|
||||
this.shape,
|
||||
this.color,
|
||||
this.enableFeedback,
|
||||
}) : assert(itemBuilder != null),
|
||||
assert(offset != null),
|
||||
assert(enabled != null),
|
||||
|
@ -1029,6 +1030,16 @@ class PopupMenuButton<T> extends StatefulWidget {
|
|||
/// Theme.of(context).cardColor is used.
|
||||
final Color? color;
|
||||
|
||||
/// Whether detected gestures should provide acoustic and/or haptic feedback.
|
||||
///
|
||||
/// For example, on Android a tap will produce a clicking sound and a
|
||||
/// long-press will produce a short vibration, when feedback is enabled.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Feedback] for providing platform-specific feedback to certain actions.
|
||||
final bool? enableFeedback;
|
||||
|
||||
@override
|
||||
PopupMenuButtonState<T> createState() => PopupMenuButtonState<T>();
|
||||
}
|
||||
|
@ -1109,6 +1120,10 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bool enableFeedback = widget.enableFeedback
|
||||
?? PopupMenuTheme.of(context).enableFeedback
|
||||
?? true;
|
||||
|
||||
assert(debugCheckHasMaterialLocalizations(context));
|
||||
|
||||
if (widget.child != null)
|
||||
|
@ -1118,6 +1133,7 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
|||
onTap: widget.enabled ? showButtonMenu : null,
|
||||
canRequestFocus: _canRequestFocus,
|
||||
child: widget.child,
|
||||
enableFeedback: enableFeedback,
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -1126,6 +1142,7 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
|||
padding: widget.padding,
|
||||
tooltip: widget.tooltip ?? MaterialLocalizations.of(context).showMenuTooltip,
|
||||
onPressed: widget.enabled ? showButtonMenu : null,
|
||||
enableFeedback: enableFeedback,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ class PopupMenuThemeData with Diagnosticable {
|
|||
this.shape,
|
||||
this.elevation,
|
||||
this.textStyle,
|
||||
this.enableFeedback,
|
||||
});
|
||||
|
||||
/// The background color of the popup menu.
|
||||
|
@ -51,6 +52,11 @@ class PopupMenuThemeData with Diagnosticable {
|
|||
/// The text style of items in the popup menu.
|
||||
final TextStyle? textStyle;
|
||||
|
||||
/// If specified, defines the feedback property for [PopupMenuButton].
|
||||
///
|
||||
/// If [PopupMenuButton.enableFeedback] is provided, [enableFeedback] is ignored.
|
||||
final bool? enableFeedback;
|
||||
|
||||
/// Creates a copy of this object with the given fields replaced with the
|
||||
/// new values.
|
||||
PopupMenuThemeData copyWith({
|
||||
|
@ -58,12 +64,14 @@ class PopupMenuThemeData with Diagnosticable {
|
|||
ShapeBorder? shape,
|
||||
double? elevation,
|
||||
TextStyle? textStyle,
|
||||
bool? enableFeedback,
|
||||
}) {
|
||||
return PopupMenuThemeData(
|
||||
color: color ?? this.color,
|
||||
shape: shape ?? this.shape,
|
||||
elevation: elevation ?? this.elevation,
|
||||
textStyle: textStyle ?? this.textStyle,
|
||||
enableFeedback: enableFeedback ?? this.enableFeedback,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -81,6 +89,7 @@ class PopupMenuThemeData with Diagnosticable {
|
|||
shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
|
||||
elevation: lerpDouble(a?.elevation, b?.elevation, t),
|
||||
textStyle: TextStyle.lerp(a?.textStyle, b?.textStyle, t),
|
||||
enableFeedback: t < 0.5 ? a?.enableFeedback : b?.enableFeedback,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -91,6 +100,7 @@ class PopupMenuThemeData with Diagnosticable {
|
|||
shape,
|
||||
elevation,
|
||||
textStyle,
|
||||
enableFeedback,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -104,7 +114,8 @@ class PopupMenuThemeData with Diagnosticable {
|
|||
&& other.elevation == elevation
|
||||
&& other.color == color
|
||||
&& other.shape == shape
|
||||
&& other.textStyle == textStyle;
|
||||
&& other.textStyle == textStyle
|
||||
&& other.enableFeedback == enableFeedback;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -114,6 +125,7 @@ class PopupMenuThemeData with Diagnosticable {
|
|||
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
|
||||
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TextStyle>('text style', textStyle, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<bool>('enableFeedback', enableFeedback, defaultValue: null));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../widgets/semantics_tester.dart';
|
||||
import 'feedback_tester.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Navigator.push works within a PopupMenuButton', (WidgetTester tester) async {
|
||||
|
@ -1799,6 +1800,79 @@ void main() {
|
|||
lessThan(600 - windowPaddingBottom), // Device height is 600.
|
||||
);
|
||||
});
|
||||
|
||||
group('feedback', () {
|
||||
late FeedbackTester feedback;
|
||||
|
||||
setUp(() {
|
||||
feedback = FeedbackTester();
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
feedback.dispose();
|
||||
});
|
||||
|
||||
Widget buildFrame({ bool? widgetEnableFeedack, bool? themeEnableFeedback }) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: PopupMenuTheme(
|
||||
data: PopupMenuThemeData(
|
||||
enableFeedback: themeEnableFeedback,
|
||||
),
|
||||
child: PopupMenuButton<int>(
|
||||
enableFeedback: widgetEnableFeedack,
|
||||
child: const Text('Show Menu'),
|
||||
itemBuilder: (BuildContext context) {
|
||||
return <PopupMenuItem<int>>[
|
||||
const PopupMenuItem<int>(
|
||||
value: 1,
|
||||
child: Text('One'),
|
||||
),
|
||||
];
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('PopupMenuButton enableFeedback works properly', (WidgetTester tester) async {
|
||||
//PopupMenuButton with enabled feedback
|
||||
await tester.pumpWidget(buildFrame(widgetEnableFeedack: true));
|
||||
await tester.tap(find.text('Show Menu'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(feedback.clickSoundCount, 1);
|
||||
expect(feedback.hapticCount, 0);
|
||||
|
||||
//PopupMenuButton with disabled feedback
|
||||
await tester.pumpWidget(buildFrame(widgetEnableFeedack: false));
|
||||
await tester.tap(find.text('Show Menu'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(feedback.clickSoundCount, 1);
|
||||
expect(feedback.hapticCount, 0);
|
||||
|
||||
//PopupMenuButton with enabled feedback by default
|
||||
await tester.pumpWidget(buildFrame());
|
||||
await tester.tap(find.text('Show Menu'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(feedback.clickSoundCount, 2);
|
||||
expect(feedback.hapticCount, 0);
|
||||
|
||||
//PopupMenu with disabled feedback using PopupMenuButtonTheme
|
||||
await tester.pumpWidget(buildFrame(themeEnableFeedback: false));
|
||||
await tester.tap(find.text('Show Menu'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(feedback.clickSoundCount, 2);
|
||||
expect(feedback.hapticCount, 0);
|
||||
|
||||
//PopupMenu enableFeedback property overrides PopupMenuButtonTheme
|
||||
await tester.pumpWidget(buildFrame(widgetEnableFeedack: false,themeEnableFeedback: true));
|
||||
await tester.tap(find.text('Show Menu'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(feedback.clickSoundCount, 2);
|
||||
expect(feedback.hapticCount, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class TestApp extends StatefulWidget {
|
||||
|
|
Loading…
Reference in a new issue