Unverified Commit 57d7946b authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

Implement DropdownButton and DropdownButtonFormField onTap callback (#53105)

parent b6655330
......@@ -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.
});
}
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