Implement DropdownButton and DropdownButtonFormField onTap callback (#53105)
This commit is contained in:
@@ -787,6 +787,7 @@ class DropdownButton<T> extends StatefulWidget {
|
||||
this.hint,
|
||||
this.disabledHint,
|
||||
@required this.onChanged,
|
||||
this.onTap,
|
||||
this.elevation = 8,
|
||||
this.style,
|
||||
this.underline,
|
||||
@@ -858,6 +859,14 @@ class DropdownButton<T> extends StatefulWidget {
|
||||
/// {@endtemplate}
|
||||
final ValueChanged<T> onChanged;
|
||||
|
||||
/// Called when the dropdown button is tapped.
|
||||
///
|
||||
/// This is distinct from [onChanged], which is called when the user
|
||||
/// selects an item from the dropdown.
|
||||
///
|
||||
/// The callback will not be invoked if the dropdown button is disabled.
|
||||
final VoidCallback onTap;
|
||||
|
||||
/// A builder to customize the dropdown buttons corresponding to the
|
||||
/// [DropdownMenuItem]s in [items].
|
||||
///
|
||||
@@ -1179,6 +1188,10 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
|
||||
if (widget.onChanged != null)
|
||||
widget.onChanged(newValue.result);
|
||||
});
|
||||
|
||||
if (widget.onTap != null) {
|
||||
widget.onTap();
|
||||
}
|
||||
}
|
||||
|
||||
Action _createAction() {
|
||||
@@ -1402,6 +1415,7 @@ class DropdownButtonFormField<T> extends FormField<T> {
|
||||
DropdownButtonBuilder selectedItemBuilder,
|
||||
Widget hint,
|
||||
@required this.onChanged,
|
||||
VoidCallback onTap,
|
||||
this.decoration = const InputDecoration(),
|
||||
FormFieldSetter<T> onSaved,
|
||||
FormFieldValidator<T> validator,
|
||||
@@ -1452,6 +1466,7 @@ class DropdownButtonFormField<T> extends FormField<T> {
|
||||
selectedItemBuilder: selectedItemBuilder,
|
||||
hint: hint,
|
||||
onChanged: onChanged == null ? null : state.didChange,
|
||||
onTap: onTap,
|
||||
disabledHint: disabledHint,
|
||||
elevation: elevation,
|
||||
style: style,
|
||||
|
||||
@@ -31,6 +31,7 @@ Widget buildFormFrame({
|
||||
int elevation = 8,
|
||||
String value = 'two',
|
||||
ValueChanged<String> onChanged,
|
||||
VoidCallback onTap,
|
||||
Widget icon,
|
||||
Color iconDisabledColor,
|
||||
Color iconEnabledColor,
|
||||
@@ -58,6 +59,7 @@ Widget buildFormFrame({
|
||||
hint: hint,
|
||||
disabledHint: disabledHint,
|
||||
onChanged: onChanged,
|
||||
onTap: onTap,
|
||||
icon: icon,
|
||||
iconSize: iconSize,
|
||||
iconDisabledColor: iconDisabledColor,
|
||||
@@ -669,4 +671,48 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Two as an Arabic numeral: 2'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('DropdownButton onTap callback is called when defined', (WidgetTester tester) async {
|
||||
int dropdownButtonTapCounter = 0;
|
||||
String value = 'one';
|
||||
void onChanged(String newValue) { value = newValue; }
|
||||
void onTap() { dropdownButtonTapCounter += 1; }
|
||||
|
||||
Widget build() => buildFormFrame(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
onTap: onTap,
|
||||
);
|
||||
await tester.pumpWidget(build());
|
||||
|
||||
expect(dropdownButtonTapCounter, 0);
|
||||
|
||||
// Tap dropdown button.
|
||||
await tester.tap(find.text('one'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(value, equals('one'));
|
||||
expect(dropdownButtonTapCounter, 1); // Should update counter.
|
||||
|
||||
// Tap dropdown menu item.
|
||||
await tester.tap(find.text('three').last);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(value, equals('three'));
|
||||
expect(dropdownButtonTapCounter, 1); // Should not change.
|
||||
|
||||
// Tap dropdown button again.
|
||||
await tester.tap(find.text('three'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(value, equals('three'));
|
||||
expect(dropdownButtonTapCounter, 2); // Should update counter.
|
||||
|
||||
// Tap dropdown menu item.
|
||||
await tester.tap(find.text('two').last);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(value, equals('two'));
|
||||
expect(dropdownButtonTapCounter, 2); // Should not change.
|
||||
});
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ Widget buildFrame({
|
||||
Key buttonKey,
|
||||
String value = 'two',
|
||||
ValueChanged<String> onChanged,
|
||||
VoidCallback onTap,
|
||||
Widget icon,
|
||||
Color iconDisabledColor,
|
||||
Color iconEnabledColor,
|
||||
@@ -66,6 +67,7 @@ Widget buildFrame({
|
||||
hint: hint,
|
||||
disabledHint: disabledHint,
|
||||
onChanged: onChanged,
|
||||
onTap: onTap,
|
||||
icon: icon,
|
||||
iconSize: iconSize,
|
||||
iconDisabledColor: iconDisabledColor,
|
||||
@@ -2314,4 +2316,49 @@ void main() {
|
||||
// tree, causing it to lose focus.
|
||||
expect(Focus.of(tester.element(find.byKey(const ValueKey<int>(91)).last)).hasPrimaryFocus, isFalse);
|
||||
}, skip: kIsWeb);
|
||||
|
||||
testWidgets('DropdownButton onTap callback is called when defined', (WidgetTester tester) async {
|
||||
int dropdownButtonTapCounter = 0;
|
||||
String value = 'one';
|
||||
|
||||
void onChanged(String newValue) { value = newValue; }
|
||||
void onTap() { dropdownButtonTapCounter += 1; }
|
||||
|
||||
Widget build() => buildFrame(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
onTap: onTap,
|
||||
);
|
||||
await tester.pumpWidget(build());
|
||||
|
||||
expect(dropdownButtonTapCounter, 0);
|
||||
|
||||
// Tap dropdown button.
|
||||
await tester.tap(find.text('one'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(value, equals('one'));
|
||||
expect(dropdownButtonTapCounter, 1); // Should update counter.
|
||||
|
||||
// Tap dropdown menu item.
|
||||
await tester.tap(find.text('three').last);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(value, equals('three'));
|
||||
expect(dropdownButtonTapCounter, 1); // Should not change.
|
||||
|
||||
// Tap dropdown button again.
|
||||
await tester.tap(find.text('three'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(value, equals('three'));
|
||||
expect(dropdownButtonTapCounter, 2); // Should update counter.
|
||||
|
||||
// Tap dropdown menu item.
|
||||
await tester.tap(find.text('two').last);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(value, equals('two'));
|
||||
expect(dropdownButtonTapCounter, 2); // Should not change.
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user