Added enableFeedback property to DropdownButton (#69880)
This commit is contained in:
@@ -97,6 +97,7 @@ class _DropdownMenuItemButton<T> extends StatefulWidget {
|
||||
required this.buttonRect,
|
||||
required this.constraints,
|
||||
required this.itemIndex,
|
||||
required this.enableFeedback,
|
||||
}) : super(key: key);
|
||||
|
||||
final _DropdownRoute<T> route;
|
||||
@@ -104,6 +105,7 @@ class _DropdownMenuItemButton<T> extends StatefulWidget {
|
||||
final Rect buttonRect;
|
||||
final BoxConstraints constraints;
|
||||
final int itemIndex;
|
||||
final bool enableFeedback;
|
||||
|
||||
@override
|
||||
_DropdownMenuItemButtonState<T> createState() => _DropdownMenuItemButtonState<T>();
|
||||
@@ -173,6 +175,7 @@ class _DropdownMenuItemButtonState<T> extends State<_DropdownMenuItemButton<T>>
|
||||
if (dropdownMenuItem.enabled) {
|
||||
child = InkWell(
|
||||
autofocus: widget.itemIndex == widget.route.selectedIndex,
|
||||
enableFeedback: widget.enableFeedback,
|
||||
child: child,
|
||||
onTap: _handleOnTap,
|
||||
onFocusChange: _handleFocusChange,
|
||||
@@ -197,6 +200,7 @@ class _DropdownMenu<T> extends StatefulWidget {
|
||||
required this.buttonRect,
|
||||
required this.constraints,
|
||||
this.dropdownColor,
|
||||
required this.enableFeedback,
|
||||
}) : super(key: key);
|
||||
|
||||
final _DropdownRoute<T> route;
|
||||
@@ -204,6 +208,7 @@ class _DropdownMenu<T> extends StatefulWidget {
|
||||
final Rect buttonRect;
|
||||
final BoxConstraints constraints;
|
||||
final Color? dropdownColor;
|
||||
final bool enableFeedback;
|
||||
|
||||
@override
|
||||
_DropdownMenuState<T> createState() => _DropdownMenuState<T>();
|
||||
@@ -253,6 +258,7 @@ class _DropdownMenuState<T> extends State<_DropdownMenu<T>> {
|
||||
buttonRect: widget.buttonRect,
|
||||
constraints: widget.constraints,
|
||||
itemIndex: itemIndex,
|
||||
enableFeedback: widget.enableFeedback,
|
||||
),
|
||||
];
|
||||
|
||||
@@ -411,6 +417,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
|
||||
this.itemHeight,
|
||||
this.dropdownColor,
|
||||
this.menuMaxHeight,
|
||||
required this.enableFeedback,
|
||||
}) : assert(style != null),
|
||||
itemHeights = List<double>.filled(items.length, itemHeight ?? kMinInteractiveDimension);
|
||||
|
||||
@@ -424,7 +431,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
|
||||
final double? itemHeight;
|
||||
final Color? dropdownColor;
|
||||
final double? menuMaxHeight;
|
||||
|
||||
final bool enableFeedback;
|
||||
|
||||
final List<double> itemHeights;
|
||||
ScrollController? scrollController;
|
||||
@@ -456,6 +463,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
|
||||
capturedThemes: capturedThemes,
|
||||
style: style,
|
||||
dropdownColor: dropdownColor,
|
||||
enableFeedback: enableFeedback,
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -551,6 +559,7 @@ class _DropdownRoutePage<T> extends StatelessWidget {
|
||||
required this.capturedThemes,
|
||||
this.style,
|
||||
required this.dropdownColor,
|
||||
required this.enableFeedback,
|
||||
}) : super(key: key);
|
||||
|
||||
final _DropdownRoute<T> route;
|
||||
@@ -563,6 +572,7 @@ class _DropdownRoutePage<T> extends StatelessWidget {
|
||||
final CapturedThemes capturedThemes;
|
||||
final TextStyle? style;
|
||||
final Color? dropdownColor;
|
||||
final bool enableFeedback;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -586,6 +596,7 @@ class _DropdownRoutePage<T> extends StatelessWidget {
|
||||
buttonRect: buttonRect,
|
||||
constraints: constraints,
|
||||
dropdownColor: dropdownColor,
|
||||
enableFeedback: enableFeedback,
|
||||
);
|
||||
|
||||
return MediaQuery.removePadding(
|
||||
@@ -854,6 +865,7 @@ class DropdownButton<T> extends StatefulWidget {
|
||||
this.autofocus = false,
|
||||
this.dropdownColor,
|
||||
this.menuMaxHeight,
|
||||
this.enableFeedback,
|
||||
// When adding new arguments, consider adding similar arguments to
|
||||
// DropdownButtonFormField.
|
||||
}) : assert(items == null || items.isEmpty || value == null ||
|
||||
@@ -1114,6 +1126,18 @@ class DropdownButton<T> extends StatefulWidget {
|
||||
/// and bottom of the menu by at one menu item's height.
|
||||
final double? menuMaxHeight;
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// By default, platform-specific feedback is enabled.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Feedback] for providing platform-specific feedback to certain actions.
|
||||
final bool? enableFeedback;
|
||||
|
||||
@override
|
||||
_DropdownButtonState<T> createState() => _DropdownButtonState<T>();
|
||||
}
|
||||
@@ -1266,6 +1290,7 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
|
||||
itemHeight: widget.itemHeight,
|
||||
dropdownColor: widget.dropdownColor,
|
||||
menuMaxHeight: widget.menuMaxHeight,
|
||||
enableFeedback: widget.enableFeedback ?? true,
|
||||
);
|
||||
|
||||
navigator.push(_dropdownRoute!).then<void>((_DropdownRouteResult<T>? newValue) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:flutter/services.dart';
|
||||
|
||||
import '../rendering/mock_canvas.dart';
|
||||
import '../widgets/semantics_tester.dart';
|
||||
import 'feedback_tester.dart';
|
||||
|
||||
const List<String> menuItems = <String>['one', 'two', 'three', 'four'];
|
||||
void onChanged<T>(T _) { }
|
||||
@@ -3242,4 +3243,75 @@ void main() {
|
||||
final Element disabledItem = tester.element(find.text('disabled').hitTestable());
|
||||
expect(Focus.maybeOf(disabledItem), null, reason: 'Disabled menu item should not be able to request focus');
|
||||
});
|
||||
|
||||
group('feedback', () {
|
||||
late FeedbackTester feedback;
|
||||
|
||||
setUp(() {
|
||||
feedback = FeedbackTester();
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
feedback.dispose();
|
||||
});
|
||||
|
||||
Widget feedbackBoilerplate({bool? enableFeedback}) {
|
||||
return MaterialApp(
|
||||
home : Material(
|
||||
child: DropdownButton<String>(
|
||||
value: 'One',
|
||||
enableFeedback: enableFeedback,
|
||||
underline: Container(
|
||||
height: 2,
|
||||
color: Colors.deepPurpleAccent,
|
||||
),
|
||||
onChanged: (String? value) {},
|
||||
items: <String>['One', 'Two'].map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('Dropdown with enabled feedback', (WidgetTester tester) async {
|
||||
const bool enableFeedback = true;
|
||||
|
||||
await tester.pumpWidget(feedbackBoilerplate(enableFeedback: enableFeedback));
|
||||
|
||||
await tester.tap(find.text('One'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.widgetWithText(InkWell, 'One'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(feedback.clickSoundCount, 1);
|
||||
expect(feedback.hapticCount, 0);
|
||||
});
|
||||
|
||||
testWidgets('Dropdown with disabled feedback', (WidgetTester tester) async {
|
||||
const bool enableFeedback = false;
|
||||
|
||||
await tester.pumpWidget(feedbackBoilerplate(enableFeedback: enableFeedback));
|
||||
|
||||
await tester.tap(find.text('One'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.widgetWithText(InkWell, 'One'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(feedback.clickSoundCount, 0);
|
||||
expect(feedback.hapticCount, 0);
|
||||
});
|
||||
|
||||
testWidgets('Dropdown with enabled feedback by default', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(feedbackBoilerplate());
|
||||
|
||||
await tester.tap(find.text('One'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.widgetWithText(InkWell, 'Two'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(feedback.clickSoundCount, 1);
|
||||
expect(feedback.hapticCount, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user