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.enabled = true,
|
||||||
this.shape,
|
this.shape,
|
||||||
this.color,
|
this.color,
|
||||||
|
this.enableFeedback,
|
||||||
}) : assert(itemBuilder != null),
|
}) : assert(itemBuilder != null),
|
||||||
assert(offset != null),
|
assert(offset != null),
|
||||||
assert(enabled != null),
|
assert(enabled != null),
|
||||||
@ -1029,6 +1030,16 @@ class PopupMenuButton<T> extends StatefulWidget {
|
|||||||
/// Theme.of(context).cardColor is used.
|
/// Theme.of(context).cardColor is used.
|
||||||
final Color? color;
|
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
|
@override
|
||||||
PopupMenuButtonState<T> createState() => PopupMenuButtonState<T>();
|
PopupMenuButtonState<T> createState() => PopupMenuButtonState<T>();
|
||||||
}
|
}
|
||||||
@ -1109,6 +1120,10 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final bool enableFeedback = widget.enableFeedback
|
||||||
|
?? PopupMenuTheme.of(context).enableFeedback
|
||||||
|
?? true;
|
||||||
|
|
||||||
assert(debugCheckHasMaterialLocalizations(context));
|
assert(debugCheckHasMaterialLocalizations(context));
|
||||||
|
|
||||||
if (widget.child != null)
|
if (widget.child != null)
|
||||||
@ -1118,6 +1133,7 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
|||||||
onTap: widget.enabled ? showButtonMenu : null,
|
onTap: widget.enabled ? showButtonMenu : null,
|
||||||
canRequestFocus: _canRequestFocus,
|
canRequestFocus: _canRequestFocus,
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
|
enableFeedback: enableFeedback,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1126,6 +1142,7 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
|
|||||||
padding: widget.padding,
|
padding: widget.padding,
|
||||||
tooltip: widget.tooltip ?? MaterialLocalizations.of(context).showMenuTooltip,
|
tooltip: widget.tooltip ?? MaterialLocalizations.of(context).showMenuTooltip,
|
||||||
onPressed: widget.enabled ? showButtonMenu : null,
|
onPressed: widget.enabled ? showButtonMenu : null,
|
||||||
|
enableFeedback: enableFeedback,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ class PopupMenuThemeData with Diagnosticable {
|
|||||||
this.shape,
|
this.shape,
|
||||||
this.elevation,
|
this.elevation,
|
||||||
this.textStyle,
|
this.textStyle,
|
||||||
|
this.enableFeedback,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The background color of the popup menu.
|
/// The background color of the popup menu.
|
||||||
@ -51,6 +52,11 @@ class PopupMenuThemeData with Diagnosticable {
|
|||||||
/// The text style of items in the popup menu.
|
/// The text style of items in the popup menu.
|
||||||
final TextStyle? textStyle;
|
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
|
/// Creates a copy of this object with the given fields replaced with the
|
||||||
/// new values.
|
/// new values.
|
||||||
PopupMenuThemeData copyWith({
|
PopupMenuThemeData copyWith({
|
||||||
@ -58,12 +64,14 @@ class PopupMenuThemeData with Diagnosticable {
|
|||||||
ShapeBorder? shape,
|
ShapeBorder? shape,
|
||||||
double? elevation,
|
double? elevation,
|
||||||
TextStyle? textStyle,
|
TextStyle? textStyle,
|
||||||
|
bool? enableFeedback,
|
||||||
}) {
|
}) {
|
||||||
return PopupMenuThemeData(
|
return PopupMenuThemeData(
|
||||||
color: color ?? this.color,
|
color: color ?? this.color,
|
||||||
shape: shape ?? this.shape,
|
shape: shape ?? this.shape,
|
||||||
elevation: elevation ?? this.elevation,
|
elevation: elevation ?? this.elevation,
|
||||||
textStyle: textStyle ?? this.textStyle,
|
textStyle: textStyle ?? this.textStyle,
|
||||||
|
enableFeedback: enableFeedback ?? this.enableFeedback,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +89,7 @@ class PopupMenuThemeData with Diagnosticable {
|
|||||||
shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
|
shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
|
||||||
elevation: lerpDouble(a?.elevation, b?.elevation, t),
|
elevation: lerpDouble(a?.elevation, b?.elevation, t),
|
||||||
textStyle: TextStyle.lerp(a?.textStyle, b?.textStyle, 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,
|
shape,
|
||||||
elevation,
|
elevation,
|
||||||
textStyle,
|
textStyle,
|
||||||
|
enableFeedback,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +114,8 @@ class PopupMenuThemeData with Diagnosticable {
|
|||||||
&& other.elevation == elevation
|
&& other.elevation == elevation
|
||||||
&& other.color == color
|
&& other.color == color
|
||||||
&& other.shape == shape
|
&& other.shape == shape
|
||||||
&& other.textStyle == textStyle;
|
&& other.textStyle == textStyle
|
||||||
|
&& other.enableFeedback == enableFeedback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -114,6 +125,7 @@ class PopupMenuThemeData with Diagnosticable {
|
|||||||
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
|
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
|
||||||
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
|
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<TextStyle>('text style', textStyle, 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 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../widgets/semantics_tester.dart';
|
import '../widgets/semantics_tester.dart';
|
||||||
|
import 'feedback_tester.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Navigator.push works within a PopupMenuButton', (WidgetTester tester) async {
|
testWidgets('Navigator.push works within a PopupMenuButton', (WidgetTester tester) async {
|
||||||
@ -1799,6 +1800,79 @@ void main() {
|
|||||||
lessThan(600 - windowPaddingBottom), // Device height is 600.
|
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 {
|
class TestApp extends StatefulWidget {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user