Unverified Commit 6bb412e3 authored by Qun Cheng's avatar Qun Cheng Committed by GitHub

Added `controller` and `onSelected` properties to DropdownMenu (#116259)

parent e5e21c98
...@@ -9,23 +9,31 @@ import 'package:flutter/material.dart'; ...@@ -9,23 +9,31 @@ import 'package:flutter/material.dart';
void main() => runApp(const DropdownMenuExample()); void main() => runApp(const DropdownMenuExample());
class DropdownMenuExample extends StatelessWidget { class DropdownMenuExample extends StatefulWidget {
const DropdownMenuExample({super.key}); const DropdownMenuExample({super.key});
List<DropdownMenuEntry> getEntryList() { @override
final List<DropdownMenuEntry> entries = <DropdownMenuEntry>[]; State<DropdownMenuExample> createState() => _DropdownMenuExampleState();
}
for (int index = 0; index < EntryLabel.values.length; index++) { class _DropdownMenuExampleState extends State<DropdownMenuExample> {
// Disabled item 1, 2 and 6. final TextEditingController colorController = TextEditingController();
final bool enabled = index != 1 && index != 2 && index != 6; final TextEditingController iconController = TextEditingController();
entries.add(DropdownMenuEntry(label: EntryLabel.values[index].label, enabled: enabled)); ColorLabel? selectedColor;
} IconLabel? selectedIcon;
return entries;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final List<DropdownMenuEntry> dropdownMenuEntries = getEntryList(); final List<DropdownMenuEntry<ColorLabel>> colorEntries = <DropdownMenuEntry<ColorLabel>>[];
for (final ColorLabel color in ColorLabel.values) {
colorEntries.add(
DropdownMenuEntry<ColorLabel>(value: color, label: color.label, enabled: color.label != 'Grey'));
}
final List<DropdownMenuEntry<IconLabel>> iconEntries = <DropdownMenuEntry<IconLabel>>[];
for (final IconLabel icon in IconLabel.values) {
iconEntries.add(DropdownMenuEntry<IconLabel>(value: icon, label: icon.label));
}
return MaterialApp( return MaterialApp(
theme: ThemeData( theme: ThemeData(
...@@ -34,25 +42,53 @@ class DropdownMenuExample extends StatelessWidget { ...@@ -34,25 +42,53 @@ class DropdownMenuExample extends StatelessWidget {
), ),
home: Scaffold( home: Scaffold(
body: SafeArea( body: SafeArea(
child: Padding( child: Column(
padding: const EdgeInsets.only(top: 20), children: <Widget>[
child: Row( Padding(
mainAxisAlignment: MainAxisAlignment.center, padding: const EdgeInsets.symmetric(vertical: 20),
children: <Widget>[ child: Row(
DropdownMenu( mainAxisAlignment: MainAxisAlignment.center,
label: const Text('Label'), children: <Widget>[
dropdownMenuEntries: dropdownMenuEntries, DropdownMenu<ColorLabel>(
initialSelection: ColorLabel.green,
controller: colorController,
label: const Text('Color'),
dropdownMenuEntries: colorEntries,
onSelected: (ColorLabel? color) {
setState(() {
selectedColor = color;
});
},
),
const SizedBox(width: 20),
DropdownMenu<IconLabel>(
controller: iconController,
enableFilter: true,
leadingIcon: const Icon(Icons.search),
label: const Text('Icon'),
dropdownMenuEntries: iconEntries,
inputDecorationTheme: const InputDecorationTheme(filled: true),
onSelected: (IconLabel? icon) {
setState(() {
selectedIcon = icon;
});
},
)
],
), ),
const SizedBox(width: 20), ),
DropdownMenu( if (selectedColor != null && selectedIcon != null)
enableFilter: true, Row(
leadingIcon: const Icon(Icons.search), mainAxisAlignment: MainAxisAlignment.center,
label: const Text('Label'), children: <Widget>[
dropdownMenuEntries: dropdownMenuEntries, Text('You selected a ${selectedColor?.label} ${selectedIcon?.label}'),
inputDecorationTheme: const InputDecorationTheme(filled: true), Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: Icon(selectedIcon?.icon, color: selectedColor?.color,))
],
) )
], else const Text('Please select a color and an icon.')
), ],
) )
), ),
), ),
...@@ -60,15 +96,25 @@ class DropdownMenuExample extends StatelessWidget { ...@@ -60,15 +96,25 @@ class DropdownMenuExample extends StatelessWidget {
} }
} }
enum EntryLabel { enum ColorLabel {
item0('Item 0'), blue('Blue', Colors.blue),
item1('Item 1'), pink('Pink', Colors.pink),
item2('Item 2'), green('Green', Colors.green),
item3('Item 3'), yellow('Yellow', Colors.yellow),
item4('Item 4'), grey('Grey', Colors.grey);
item5('Item 5'),
item6('Item 6'); const ColorLabel(this.label, this.color);
final String label;
final Color color;
}
enum IconLabel {
smile('Smile', Icons.sentiment_satisfied_outlined),
cloud('Cloud', Icons.cloud_outlined,),
brush('Brush', Icons.brush_outlined),
heart('Heart', Icons.favorite);
const EntryLabel(this.label); const IconLabel(this.label, this.icon);
final String label; final String label;
final IconData icon;
} }
...@@ -36,11 +36,12 @@ const double _kDefaultHorizontalPadding = 12.0; ...@@ -36,11 +36,12 @@ const double _kDefaultHorizontalPadding = 12.0;
/// See also: /// See also:
/// ///
/// * [DropdownMenu] /// * [DropdownMenu]
class DropdownMenuEntry { class DropdownMenuEntry<T> {
/// Creates an entry that is used with [DropdownMenu.dropdownMenuEntries]. /// Creates an entry that is used with [DropdownMenu.dropdownMenuEntries].
/// ///
/// [label] must be non-null. /// [label] must be non-null.
const DropdownMenuEntry({ const DropdownMenuEntry({
required this.value,
required this.label, required this.label,
this.leadingIcon, this.leadingIcon,
this.trailingIcon, this.trailingIcon,
...@@ -48,6 +49,11 @@ class DropdownMenuEntry { ...@@ -48,6 +49,11 @@ class DropdownMenuEntry {
this.style, this.style,
}); });
/// the value used to identify the entry.
///
/// This value must be unique across all entries in a [DropdownMenu].
final T value;
/// The label displayed in the center of the menu item. /// The label displayed in the center of the menu item.
final String label; final String label;
...@@ -101,7 +107,7 @@ class DropdownMenuEntry { ...@@ -101,7 +107,7 @@ class DropdownMenuEntry {
/// The [DropdownMenu] uses a [TextField] as the "anchor". /// The [DropdownMenu] uses a [TextField] as the "anchor".
/// * [TextField], which is a text input widget that uses an [InputDecoration]. /// * [TextField], which is a text input widget that uses an [InputDecoration].
/// * [DropdownMenuEntry], which is used to build the [MenuItemButton] in the [DropdownMenu] list. /// * [DropdownMenuEntry], which is used to build the [MenuItemButton] in the [DropdownMenu] list.
class DropdownMenu extends StatefulWidget { class DropdownMenu<T> extends StatefulWidget {
/// Creates a const [DropdownMenu]. /// Creates a const [DropdownMenu].
/// ///
/// The leading and trailing icons in the text field can be customized by using /// The leading and trailing icons in the text field can be customized by using
...@@ -126,6 +132,9 @@ class DropdownMenu extends StatefulWidget { ...@@ -126,6 +132,9 @@ class DropdownMenu extends StatefulWidget {
this.textStyle, this.textStyle,
this.inputDecorationTheme, this.inputDecorationTheme,
this.menuStyle, this.menuStyle,
this.controller,
this.initialSelection,
this.onSelected,
required this.dropdownMenuEntries, required this.dropdownMenuEntries,
}); });
...@@ -204,25 +213,40 @@ class DropdownMenu extends StatefulWidget { ...@@ -204,25 +213,40 @@ class DropdownMenu extends StatefulWidget {
/// The default width of the menu is set to the width of the text field. /// The default width of the menu is set to the width of the text field.
final MenuStyle? menuStyle; final MenuStyle? menuStyle;
/// Controls the text being edited or selected in the menu.
///
/// If null, this widget will create its own [TextEditingController].
final TextEditingController? controller;
/// The value used to for an initial selection.
///
/// Defaults to null.
final T? initialSelection;
/// The callback is called when a selection is made.
///
/// Defaults to null. If null, only the text field is updated.
final ValueChanged<T?>? onSelected;
/// Descriptions of the menu items in the [DropdownMenu]. /// Descriptions of the menu items in the [DropdownMenu].
/// ///
/// This is a required parameter. It is recommended that at least one [DropdownMenuEntry] /// This is a required parameter. It is recommended that at least one [DropdownMenuEntry]
/// is provided. If this is an empty list, the menu will be empty and only /// is provided. If this is an empty list, the menu will be empty and only
/// contain space for padding. /// contain space for padding.
final List<DropdownMenuEntry> dropdownMenuEntries; final List<DropdownMenuEntry<T>> dropdownMenuEntries;
@override @override
State<DropdownMenu> createState() => _DropdownMenuState(); State<DropdownMenu<T>> createState() => _DropdownMenuState<T>();
} }
class _DropdownMenuState extends State<DropdownMenu> { class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
final MenuController _controller = MenuController();
final GlobalKey _anchorKey = GlobalKey(); final GlobalKey _anchorKey = GlobalKey();
final GlobalKey _leadingKey = GlobalKey(); final GlobalKey _leadingKey = GlobalKey();
final FocusNode _textFocusNode = FocusNode(); final FocusNode _textFocusNode = FocusNode();
final TextEditingController _textEditingController = TextEditingController(); final MenuController _controller = MenuController();
late final TextEditingController _textEditingController;
late bool _enableFilter; late bool _enableFilter;
late List<DropdownMenuEntry> filteredEntries; late List<DropdownMenuEntry<T>> filteredEntries;
List<Widget>? _initialMenu; List<Widget>? _initialMenu;
int? currentHighlight; int? currentHighlight;
double? leadingPadding; double? leadingPadding;
...@@ -231,22 +255,37 @@ class _DropdownMenuState extends State<DropdownMenu> { ...@@ -231,22 +255,37 @@ class _DropdownMenuState extends State<DropdownMenu> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_textEditingController = widget.controller ?? TextEditingController();
_enableFilter = widget.enableFilter; _enableFilter = widget.enableFilter;
filteredEntries = widget.dropdownMenuEntries; filteredEntries = widget.dropdownMenuEntries;
_menuHasEnabledItem = filteredEntries.any((DropdownMenuEntry entry) => entry.enabled); _menuHasEnabledItem = filteredEntries.any((DropdownMenuEntry<T> entry) => entry.enabled);
final int index = filteredEntries.indexWhere((DropdownMenuEntry<T> entry) => entry.value == widget.initialSelection);
if (index != -1) {
_textEditingController.text = filteredEntries[index].label;
_textEditingController.selection =
TextSelection.collapsed(offset: _textEditingController.text.length);
}
refreshLeadingPadding(); refreshLeadingPadding();
} }
@override @override
void didUpdateWidget(DropdownMenu oldWidget) { void didUpdateWidget(DropdownMenu<T> oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (oldWidget.dropdownMenuEntries != widget.dropdownMenuEntries) { if (oldWidget.dropdownMenuEntries != widget.dropdownMenuEntries) {
_menuHasEnabledItem = filteredEntries.any((DropdownMenuEntry entry) => entry.enabled); _menuHasEnabledItem = filteredEntries.any((DropdownMenuEntry<T> entry) => entry.enabled);
} }
if (oldWidget.leadingIcon != widget.leadingIcon) { if (oldWidget.leadingIcon != widget.leadingIcon) {
refreshLeadingPadding(); refreshLeadingPadding();
} }
if (oldWidget.initialSelection != widget.initialSelection) {
final int index = filteredEntries.indexWhere((DropdownMenuEntry<T> entry) => entry.value == widget.initialSelection);
if (index != -1) {
_textEditingController.text = filteredEntries[index].label;
_textEditingController.selection =
TextSelection.collapsed(offset: _textEditingController.text.length);
}
}
} }
void refreshLeadingPadding() { void refreshLeadingPadding() {
...@@ -266,25 +305,25 @@ class _DropdownMenuState extends State<DropdownMenu> { ...@@ -266,25 +305,25 @@ class _DropdownMenuState extends State<DropdownMenu> {
return null; return null;
} }
List<DropdownMenuEntry> filter(List<DropdownMenuEntry> entries, TextEditingController textEditingController) { List<DropdownMenuEntry<T>> filter(List<DropdownMenuEntry<T>> entries, TextEditingController textEditingController) {
final String filterText = textEditingController.text.toLowerCase(); final String filterText = textEditingController.text.toLowerCase();
return entries return entries
.where((DropdownMenuEntry entry) => entry.label.toLowerCase().contains(filterText)) .where((DropdownMenuEntry<T> entry) => entry.label.toLowerCase().contains(filterText))
.toList(); .toList();
} }
int? search(List<DropdownMenuEntry> entries, TextEditingController textEditingController) { int? search(List<DropdownMenuEntry<T>> entries, TextEditingController textEditingController) {
final String searchText = textEditingController.value.text.toLowerCase(); final String searchText = textEditingController.value.text.toLowerCase();
if (searchText.isEmpty) { if (searchText.isEmpty) {
return null; return null;
} }
final int index = entries.indexWhere((DropdownMenuEntry entry) => entry.label.toLowerCase().contains(searchText)); final int index = entries.indexWhere((DropdownMenuEntry<T> entry) => entry.label.toLowerCase().contains(searchText));
return index != -1 ? index : null; return index != -1 ? index : null;
} }
List<Widget> _buildButtons( List<Widget> _buildButtons(
List<DropdownMenuEntry> filteredEntries, List<DropdownMenuEntry<T>> filteredEntries,
TextEditingController textEditingController, TextEditingController textEditingController,
TextDirection textDirection, TextDirection textDirection,
{ int? focusedIndex } { int? focusedIndex }
...@@ -306,7 +345,7 @@ class _DropdownMenuState extends State<DropdownMenu> { ...@@ -306,7 +345,7 @@ class _DropdownMenuState extends State<DropdownMenu> {
} }
for (int i = 0; i < filteredEntries.length; i++) { for (int i = 0; i < filteredEntries.length; i++) {
final DropdownMenuEntry entry = filteredEntries[i]; final DropdownMenuEntry<T> entry = filteredEntries[i];
ButtonStyle effectiveStyle = entry.style ?? defaultStyle; ButtonStyle effectiveStyle = entry.style ?? defaultStyle;
final Color focusedBackgroundColor = effectiveStyle.foregroundColor?.resolve(<MaterialState>{MaterialState.focused}) final Color focusedBackgroundColor = effectiveStyle.foregroundColor?.resolve(<MaterialState>{MaterialState.focused})
?? Theme.of(context).colorScheme.onSurface; ?? Theme.of(context).colorScheme.onSurface;
...@@ -328,8 +367,9 @@ class _DropdownMenuState extends State<DropdownMenu> { ...@@ -328,8 +367,9 @@ class _DropdownMenuState extends State<DropdownMenu> {
? () { ? () {
textEditingController.text = entry.label; textEditingController.text = entry.label;
textEditingController.selection = textEditingController.selection =
TextSelection.collapsed(offset: textEditingController.text.length); TextSelection.collapsed(offset: textEditingController.text.length);
currentHighlight = widget.enableSearch ? i : -1; currentHighlight = widget.enableSearch ? i : null;
widget.onSelected?.call(entry.value);
} }
: null, : null,
requestFocusOnHover: false, requestFocusOnHover: false,
...@@ -351,7 +391,8 @@ class _DropdownMenuState extends State<DropdownMenu> { ...@@ -351,7 +391,8 @@ class _DropdownMenuState extends State<DropdownMenu> {
while (!filteredEntries[currentHighlight!].enabled) { while (!filteredEntries[currentHighlight!].enabled) {
currentHighlight = (currentHighlight! - 1) % filteredEntries.length; currentHighlight = (currentHighlight! - 1) % filteredEntries.length;
} }
_textEditingController.text = filteredEntries[currentHighlight!].label; final String currentLabel = filteredEntries[currentHighlight!].label;
_textEditingController.text = currentLabel;
_textEditingController.selection = _textEditingController.selection =
TextSelection.collapsed(offset: _textEditingController.text.length); TextSelection.collapsed(offset: _textEditingController.text.length);
}); });
...@@ -366,14 +407,15 @@ class _DropdownMenuState extends State<DropdownMenu> { ...@@ -366,14 +407,15 @@ class _DropdownMenuState extends State<DropdownMenu> {
while (!filteredEntries[currentHighlight!].enabled) { while (!filteredEntries[currentHighlight!].enabled) {
currentHighlight = (currentHighlight! + 1) % filteredEntries.length; currentHighlight = (currentHighlight! + 1) % filteredEntries.length;
} }
_textEditingController.text = filteredEntries[currentHighlight!].label; final String currentLabel = filteredEntries[currentHighlight!].label;
_textEditingController.text = currentLabel;
_textEditingController.selection = _textEditingController.selection =
TextSelection.collapsed(offset: _textEditingController.text.length); TextSelection.collapsed(offset: _textEditingController.text.length);
}); });
void handlePressed(MenuController controller) { void handlePressed(MenuController controller) {
if (controller.isOpen) { if (controller.isOpen) {
currentHighlight = -1; currentHighlight = null;
controller.close(); controller.close();
} else { // close to open } else { // close to open
if (_textEditingController.text.isNotEmpty) { if (_textEditingController.text.isNotEmpty) {
...@@ -443,6 +485,7 @@ class _DropdownMenuState extends State<DropdownMenu> { ...@@ -443,6 +485,7 @@ class _DropdownMenuState extends State<DropdownMenu> {
controller: _controller, controller: _controller,
menuChildren: menu, menuChildren: menu,
crossAxisUnconstrained: false, crossAxisUnconstrained: false,
onClose: () { setState(() {}); }, // To update the status of the IconButton
builder: (BuildContext context, MenuController controller, Widget? child) { builder: (BuildContext context, MenuController controller, Widget? child) {
assert(_initialMenu != null); assert(_initialMenu != null);
final Widget trailingButton = Padding( final Widget trailingButton = Padding(
...@@ -473,16 +516,27 @@ class _DropdownMenuState extends State<DropdownMenu> { ...@@ -473,16 +516,27 @@ class _DropdownMenuState extends State<DropdownMenu> {
controller: _textEditingController, controller: _textEditingController,
onEditingComplete: () { onEditingComplete: () {
if (currentHighlight != null) { if (currentHighlight != null) {
_textEditingController.text = filteredEntries[currentHighlight!].label; final DropdownMenuEntry<T> entry = filteredEntries[currentHighlight!];
_textEditingController.selection = if (entry.enabled) {
TextSelection.collapsed(offset: _textEditingController.text.length); _textEditingController.text = entry.label;
_textEditingController.selection =
TextSelection.collapsed(offset: _textEditingController.text.length);
widget.onSelected?.call(entry.value);
}
} else {
widget.onSelected?.call(null);
}
if (!widget.enableSearch) {
currentHighlight = null;
}
if (_textEditingController.text.isNotEmpty) {
controller.close();
} }
controller.close();
}, },
onTap: () { onTap: () {
handlePressed(controller); handlePressed(controller);
}, },
onChanged: (_) { onChanged: (String text) {
controller.open(); controller.open();
setState(() { setState(() {
filteredEntries = widget.dropdownMenuEntries; filteredEntries = widget.dropdownMenuEntries;
......
...@@ -8,19 +8,19 @@ import 'package:flutter/services.dart'; ...@@ -8,19 +8,19 @@ import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
final List<DropdownMenuEntry> menuChildren = <DropdownMenuEntry>[]; final List<DropdownMenuEntry<TestMenu>> menuChildren = <DropdownMenuEntry<TestMenu>>[];
for (final TestMenu value in TestMenu.values) { for (final TestMenu value in TestMenu.values) {
final DropdownMenuEntry entry = DropdownMenuEntry(label: value.label); final DropdownMenuEntry<TestMenu> entry = DropdownMenuEntry<TestMenu>(value: value, label: value.label);
menuChildren.add(entry); menuChildren.add(entry);
} }
Widget buildTest(ThemeData themeData, List<DropdownMenuEntry> entries, Widget buildTest<T extends Enum>(ThemeData themeData, List<DropdownMenuEntry<T>> entries,
{double? width, double? menuHeight, Widget? leadingIcon, Widget? label}) { {double? width, double? menuHeight, Widget? leadingIcon, Widget? label}) {
return MaterialApp( return MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<T>(
label: label, label: label,
leadingIcon: leadingIcon, leadingIcon: leadingIcon,
width: width, width: width,
...@@ -80,7 +80,7 @@ void main() { ...@@ -80,7 +80,7 @@ void main() {
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: SafeArea( body: SafeArea(
child: DropdownMenu( child: DropdownMenu<TestMenu>(
enabled: false, enabled: false,
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
...@@ -115,7 +115,7 @@ void main() { ...@@ -115,7 +115,7 @@ void main() {
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: SafeArea( body: SafeArea(
child: DropdownMenu( child: DropdownMenu<TestMenu>(
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
), ),
...@@ -127,7 +127,7 @@ void main() { ...@@ -127,7 +127,7 @@ void main() {
final Size anchorSize = tester.getSize(textField); final Size anchorSize = tester.getSize(textField);
expect(anchorSize, const Size(180.0, 54.0)); expect(anchorSize, const Size(180.0, 54.0));
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Finder menuMaterial = find.ancestor( final Finder menuMaterial = find.ancestor(
...@@ -145,7 +145,7 @@ void main() { ...@@ -145,7 +145,7 @@ void main() {
final Size size = tester.getSize(anchor); final Size size = tester.getSize(anchor);
expect(size, const Size(200.0, 54.0)); expect(size, const Size(200.0, 54.0));
await tester.tap(find.byType(DropdownMenu)); await tester.tap(anchor);
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Finder updatedMenu = find.ancestor( final Finder updatedMenu = find.ancestor(
...@@ -158,19 +158,19 @@ void main() { ...@@ -158,19 +158,19 @@ void main() {
testWidgets('The width property can customize the width of the dropdown menu', (WidgetTester tester) async { testWidgets('The width property can customize the width of the dropdown menu', (WidgetTester tester) async {
final ThemeData themeData = ThemeData(); final ThemeData themeData = ThemeData();
final List<DropdownMenuEntry> shortMenuItems = <DropdownMenuEntry>[]; final List<DropdownMenuEntry<ShortMenu>> shortMenuItems = <DropdownMenuEntry<ShortMenu>>[];
for (final ShortMenu value in ShortMenu.values) { for (final ShortMenu value in ShortMenu.values) {
final DropdownMenuEntry entry = DropdownMenuEntry(label: value.label); final DropdownMenuEntry<ShortMenu> entry = DropdownMenuEntry<ShortMenu>(value: value, label: value.label);
shortMenuItems.add(entry); shortMenuItems.add(entry);
} }
const double customBigWidth = 250.0; const double customBigWidth = 250.0;
await tester.pumpWidget(buildTest(themeData, shortMenuItems, width: customBigWidth)); await tester.pumpWidget(buildTest(themeData, shortMenuItems, width: customBigWidth));
RenderBox box = tester.firstRenderObject(find.byType(DropdownMenu)); RenderBox box = tester.firstRenderObject(find.byType(DropdownMenu<ShortMenu>));
expect(box.size.width, customBigWidth); expect(box.size.width, customBigWidth);
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<ShortMenu>));
await tester.pump(); await tester.pump();
expect(find.byType(MenuItemButton), findsNWidgets(6)); expect(find.byType(MenuItemButton), findsNWidgets(6));
Size buttonSize = tester.getSize(find.widgetWithText(MenuItemButton, 'I0').last); Size buttonSize = tester.getSize(find.widgetWithText(MenuItemButton, 'I0').last);
...@@ -180,10 +180,10 @@ void main() { ...@@ -180,10 +180,10 @@ void main() {
await tester.pumpWidget(Container()); await tester.pumpWidget(Container());
const double customSmallWidth = 100.0; const double customSmallWidth = 100.0;
await tester.pumpWidget(buildTest(themeData, shortMenuItems, width: customSmallWidth)); await tester.pumpWidget(buildTest(themeData, shortMenuItems, width: customSmallWidth));
box = tester.firstRenderObject(find.byType(DropdownMenu)); box = tester.firstRenderObject(find.byType(DropdownMenu<ShortMenu>));
expect(box.size.width, customSmallWidth); expect(box.size.width, customSmallWidth);
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<ShortMenu>));
await tester.pump(); await tester.pump();
expect(find.byType(MenuItemButton), findsNWidgets(6)); expect(find.byType(MenuItemButton), findsNWidgets(6));
buttonSize = tester.getSize(find.widgetWithText(MenuItemButton, 'I0').last); buttonSize = tester.getSize(find.widgetWithText(MenuItemButton, 'I0').last);
...@@ -195,7 +195,7 @@ void main() { ...@@ -195,7 +195,7 @@ void main() {
final ThemeData themeData = ThemeData(); final ThemeData themeData = ThemeData();
await tester.pumpWidget(buildTest(themeData, menuChildren)); await tester.pumpWidget(buildTest(themeData, menuChildren));
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Element firstItem = tester.element(find.widgetWithText(MenuItemButton, 'Item 0').last); final Element firstItem = tester.element(find.widgetWithText(MenuItemButton, 'Item 0').last);
...@@ -219,7 +219,7 @@ void main() { ...@@ -219,7 +219,7 @@ void main() {
await tester.pumpWidget(buildTest(themeData, menuChildren, menuHeight: 100)); await tester.pumpWidget(buildTest(themeData, menuChildren, menuHeight: 100));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Finder updatedMenu = find.ancestor( final Finder updatedMenu = find.ancestor(
...@@ -240,7 +240,7 @@ void main() { ...@@ -240,7 +240,7 @@ void main() {
final Finder label = find.text('label'); final Finder label = find.text('label');
final Offset labelTopLeft = tester.getTopLeft(label); final Offset labelTopLeft = tester.getTopLeft(label);
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Finder itemText = find.text('Item 0').last; final Finder itemText = find.text('Item 0').last;
final Offset itemTextTopLeft = tester.getTopLeft(itemText); final Offset itemTextTopLeft = tester.getTopLeft(itemText);
...@@ -259,7 +259,7 @@ void main() { ...@@ -259,7 +259,7 @@ void main() {
final Finder updatedLabel = find.text('label'); final Finder updatedLabel = find.text('label');
final Offset updatedLabelTopLeft = tester.getTopLeft(updatedLabel); final Offset updatedLabelTopLeft = tester.getTopLeft(updatedLabel);
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Finder updatedItemText = find.text('Item 0').last; final Finder updatedItemText = find.text('Item 0').last;
final Offset updatedItemTextTopLeft = tester.getTopLeft(updatedItemText); final Offset updatedItemTextTopLeft = tester.getTopLeft(updatedItemText);
...@@ -282,7 +282,7 @@ void main() { ...@@ -282,7 +282,7 @@ void main() {
final Finder updatedLabel1 = find.text('label'); final Finder updatedLabel1 = find.text('label');
final Offset updatedLabelTopLeft1 = tester.getTopLeft(updatedLabel1); final Offset updatedLabelTopLeft1 = tester.getTopLeft(updatedLabel1);
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Finder updatedItemText1 = find.text('Item 0').last; final Finder updatedItemText1 = find.text('Item 0').last;
final Offset updatedItemTextTopLeft1 = tester.getTopLeft(updatedItemText1); final Offset updatedItemTextTopLeft1 = tester.getTopLeft(updatedItemText1);
...@@ -301,7 +301,7 @@ void main() { ...@@ -301,7 +301,7 @@ void main() {
home: Scaffold( home: Scaffold(
body: Directionality( body: Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
child: DropdownMenu( child: DropdownMenu<TestMenu>(
label: const Text('label'), label: const Text('label'),
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
...@@ -312,7 +312,7 @@ void main() { ...@@ -312,7 +312,7 @@ void main() {
final Finder label = find.text('label'); final Finder label = find.text('label');
final Offset labelTopRight = tester.getTopRight(label); final Offset labelTopRight = tester.getTopRight(label);
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Finder itemText = find.text('Item 0').last; final Finder itemText = find.text('Item 0').last;
final Offset itemTextTopRight = tester.getTopRight(itemText); final Offset itemTextTopRight = tester.getTopRight(itemText);
...@@ -326,7 +326,7 @@ void main() { ...@@ -326,7 +326,7 @@ void main() {
home: Scaffold( home: Scaffold(
body: Directionality( body: Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
child: DropdownMenu( child: DropdownMenu<TestMenu>(
leadingIcon: const Icon(Icons.search), leadingIcon: const Icon(Icons.search),
label: const Text('label'), label: const Text('label'),
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
...@@ -338,11 +338,11 @@ void main() { ...@@ -338,11 +338,11 @@ void main() {
final Finder leadingIcon = find.widgetWithIcon(Container, Icons.search); final Finder leadingIcon = find.widgetWithIcon(Container, Icons.search);
final double iconWidth = tester.getSize(leadingIcon).width; final double iconWidth = tester.getSize(leadingIcon).width;
final Offset dropdownMenuTopRight = tester.getTopRight(find.byType(DropdownMenu)); final Offset dropdownMenuTopRight = tester.getTopRight(find.byType(DropdownMenu<TestMenu>));
final Finder updatedLabel = find.text('label'); final Finder updatedLabel = find.text('label');
final Offset updatedLabelTopRight = tester.getTopRight(updatedLabel); final Offset updatedLabelTopRight = tester.getTopRight(updatedLabel);
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Finder updatedItemText = find.text('Item 0').last; final Finder updatedItemText = find.text('Item 0').last;
final Offset updatedItemTextTopRight = tester.getTopRight(updatedItemText); final Offset updatedItemTextTopRight = tester.getTopRight(updatedItemText);
...@@ -358,7 +358,7 @@ void main() { ...@@ -358,7 +358,7 @@ void main() {
home: Scaffold( home: Scaffold(
body: Directionality( body: Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
child: DropdownMenu( child: DropdownMenu<TestMenu>(
leadingIcon: const SizedBox(width: 75.0, child: Icon(Icons.search)), leadingIcon: const SizedBox(width: 75.0, child: Icon(Icons.search)),
label: const Text('label'), label: const Text('label'),
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
...@@ -370,11 +370,11 @@ void main() { ...@@ -370,11 +370,11 @@ void main() {
final Finder largeLeadingIcon = find.widgetWithIcon(Container, Icons.search); final Finder largeLeadingIcon = find.widgetWithIcon(Container, Icons.search);
final double largeIconWidth = tester.getSize(largeLeadingIcon).width; final double largeIconWidth = tester.getSize(largeLeadingIcon).width;
final Offset updatedDropdownMenuTopRight = tester.getTopRight(find.byType(DropdownMenu)); final Offset updatedDropdownMenuTopRight = tester.getTopRight(find.byType(DropdownMenu<TestMenu>));
final Finder updatedLabel1 = find.text('label'); final Finder updatedLabel1 = find.text('label');
final Offset updatedLabelTopRight1 = tester.getTopRight(updatedLabel1); final Offset updatedLabelTopRight1 = tester.getTopRight(updatedLabel1);
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Finder updatedItemText1 = find.text('Item 0').last; final Finder updatedItemText1 = find.text('Item 0').last;
final Offset updatedItemTextTopRight1 = tester.getTopRight(updatedItemText1); final Offset updatedItemTextTopRight1 = tester.getTopRight(updatedItemText1);
...@@ -407,7 +407,7 @@ void main() { ...@@ -407,7 +407,7 @@ void main() {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<TestMenu>(
trailingIcon: const Icon(Icons.ac_unit), trailingIcon: const Icon(Icons.ac_unit),
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
...@@ -433,14 +433,14 @@ void main() { ...@@ -433,14 +433,14 @@ void main() {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<TestMenu>(
trailingIcon: const Icon(Icons.ac_unit), trailingIcon: const Icon(Icons.ac_unit),
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
), ),
)); ));
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump(); await tester.pump();
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown); await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
...@@ -475,13 +475,13 @@ void main() { ...@@ -475,13 +475,13 @@ void main() {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<TestMenu>(
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
), ),
)); ));
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump(); await tester.pump();
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp); await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
...@@ -517,14 +517,14 @@ void main() { ...@@ -517,14 +517,14 @@ void main() {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<TestMenu>(
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
), ),
)); ));
// Open the menu // Open the menu
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump(); await tester.pump();
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown); await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
...@@ -547,14 +547,14 @@ void main() { ...@@ -547,14 +547,14 @@ void main() {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<TestMenu>(
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
), ),
)); ));
// Open the menu // Open the menu
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump(); await tester.pump();
await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp); await simulateKeyDownEvent(LogicalKeyboardKey.arrowUp);
...@@ -574,18 +574,18 @@ void main() { ...@@ -574,18 +574,18 @@ void main() {
testWidgets('Disabled button will be skipped while pressing up/down key', (WidgetTester tester) async { testWidgets('Disabled button will be skipped while pressing up/down key', (WidgetTester tester) async {
final ThemeData themeData = ThemeData(); final ThemeData themeData = ThemeData();
final List<DropdownMenuEntry> menuWithDisabledItems = <DropdownMenuEntry>[ final List<DropdownMenuEntry<TestMenu>> menuWithDisabledItems = <DropdownMenuEntry<TestMenu>>[
const DropdownMenuEntry(label: 'Item 0'), const DropdownMenuEntry<TestMenu>(value: TestMenu.mainMenu0, label: 'Item 0'),
const DropdownMenuEntry(label: 'Item 1', enabled: false), const DropdownMenuEntry<TestMenu>(value: TestMenu.mainMenu1, label: 'Item 1', enabled: false),
const DropdownMenuEntry(label: 'Item 2', enabled: false), const DropdownMenuEntry<TestMenu>(value: TestMenu.mainMenu2, label: 'Item 2', enabled: false),
const DropdownMenuEntry(label: 'Item 3'), const DropdownMenuEntry<TestMenu>(value: TestMenu.mainMenu3, label: 'Item 3'),
const DropdownMenuEntry(label: 'Item 4'), const DropdownMenuEntry<TestMenu>(value: TestMenu.mainMenu4, label: 'Item 4'),
const DropdownMenuEntry(label: 'Item 5', enabled: false), const DropdownMenuEntry<TestMenu>(value: TestMenu.mainMenu5, label: 'Item 5', enabled: false),
]; ];
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<TestMenu>(
dropdownMenuEntries: menuWithDisabledItems, dropdownMenuEntries: menuWithDisabledItems,
), ),
), ),
...@@ -593,7 +593,7 @@ void main() { ...@@ -593,7 +593,7 @@ void main() {
await tester.pump(); await tester.pump();
// Open the menu // Open the menu
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown); await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
...@@ -621,14 +621,14 @@ void main() { ...@@ -621,14 +621,14 @@ void main() {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<TestMenu>(
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
), ),
)); ));
// Open the menu // Open the menu
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump(); await tester.pump();
await tester.enterText(find.byType(TextField).first, 'Menu 1'); await tester.enterText(find.byType(TextField).first, 'Menu 1');
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -645,14 +645,14 @@ void main() { ...@@ -645,14 +645,14 @@ void main() {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<TestMenu>(
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
), ),
)); ));
// Open the menu // Open the menu
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump(); await tester.pump();
await tester.enterText(find.byType(TextField).first, 'Menu 1'); await tester.enterText(find.byType(TextField).first, 'Menu 1');
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -691,14 +691,14 @@ void main() { ...@@ -691,14 +691,14 @@ void main() {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<TestMenu>(
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
), ),
)); ));
// Open the menu // Open the menu
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump(); await tester.pump();
await tester.enterText(find.byType(TextField).first, 'Menu 1'); await tester.enterText(find.byType(TextField).first, 'Menu 1');
...@@ -714,7 +714,7 @@ void main() { ...@@ -714,7 +714,7 @@ void main() {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: themeData,
home: Scaffold( home: Scaffold(
body: DropdownMenu( body: DropdownMenu<TestMenu>(
enableFilter: true, enableFilter: true,
dropdownMenuEntries: menuChildren, dropdownMenuEntries: menuChildren,
), ),
...@@ -722,7 +722,7 @@ void main() { ...@@ -722,7 +722,7 @@ void main() {
)); ));
// Open the menu // Open the menu
await tester.tap(find.byType(DropdownMenu)); await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump(); await tester.pump();
await tester.enterText(find await tester.enterText(find
...@@ -738,6 +738,150 @@ void main() { ...@@ -738,6 +738,150 @@ void main() {
} }
} }
}); });
testWidgets('The controller can access the value in the input field', (WidgetTester tester) async {
final ThemeData themeData = ThemeData();
final TextEditingController controller = TextEditingController();
await tester.pumpWidget(MaterialApp(
theme: themeData,
home: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Scaffold(
body: DropdownMenu<TestMenu>(
enableFilter: true,
dropdownMenuEntries: menuChildren,
controller: controller,
),
);
}
),
));
// Open the menu
await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump();
final Finder item3 = find.widgetWithText(MenuItemButton, 'Item 3').last;
await tester.tap(item3);
await tester.pumpAndSettle();
expect(controller.text, 'Item 3');
await tester.enterText(find.byType(TextField).first, 'New Item');
expect(controller.text, 'New Item');
});
testWidgets('The onSelected gets called only when a selection is made', (WidgetTester tester) async {
int selectionCount = 0;
final ThemeData themeData = ThemeData();
final List<DropdownMenuEntry<TestMenu>> menuWithDisabledItems = <DropdownMenuEntry<TestMenu>>[
const DropdownMenuEntry<TestMenu>(value: TestMenu.mainMenu0, label: 'Item 0'),
const DropdownMenuEntry<TestMenu>(value: TestMenu.mainMenu0, label: 'Item 1', enabled: false),
const DropdownMenuEntry<TestMenu>(value: TestMenu.mainMenu0, label: 'Item 2'),
const DropdownMenuEntry<TestMenu>(value: TestMenu.mainMenu0, label: 'Item 3'),
];
final TextEditingController controller = TextEditingController();
await tester.pumpWidget(MaterialApp(
theme: themeData,
home: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Scaffold(
body: DropdownMenu<TestMenu>(
dropdownMenuEntries: menuWithDisabledItems,
controller: controller,
onSelected: (_) {
setState(() {
selectionCount++;
});
},
),
);
}
),
));
// Open the menu
await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump();
// Test onSelected on key press
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
await tester.pumpAndSettle();
await tester.testTextInput.receiveAction(TextInputAction.done);
await tester.pumpAndSettle();
expect(selectionCount, 1);
// Disabled item doesn't trigger onSelected callback.
await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump();
final Finder item1 = find.widgetWithText(MenuItemButton, 'Item 1').last;
await tester.tap(item1);
await tester.pumpAndSettle();
expect(controller.text, 'Item 0');
expect(selectionCount, 1);
final Finder item2 = find.widgetWithText(MenuItemButton, 'Item 2').last;
await tester.tap(item2);
await tester.pumpAndSettle();
expect(controller.text, 'Item 2');
expect(selectionCount, 2);
await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump();
final Finder item3 = find.widgetWithText(MenuItemButton, 'Item 3').last;
await tester.tap(item3);
await tester.pumpAndSettle();
expect(controller.text, 'Item 3');
expect(selectionCount, 3);
// When typing something in the text field without selecting any of the options,
// the onSelected should not be called.
await tester.enterText(find.byType(TextField).first, 'New Item');
expect(controller.text, 'New Item');
expect(selectionCount, 3);
expect(find.widgetWithText(TextField, 'New Item'), findsOneWidget);
await tester.enterText(find.byType(TextField).first, '');
expect(selectionCount, 3);
expect(controller.text.isEmpty, true);
});
testWidgets('The selectedValue gives an initial text and highlights the according item', (WidgetTester tester) async {
final ThemeData themeData = ThemeData();
final TextEditingController controller = TextEditingController();
await tester.pumpWidget(MaterialApp(
theme: themeData,
home: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Scaffold(
body: DropdownMenu<TestMenu>(
initialSelection: TestMenu.mainMenu3,
dropdownMenuEntries: menuChildren,
controller: controller,
),
);
}
),
));
expect(find.widgetWithText(TextField, 'Item 3'), findsOneWidget);
// Open the menu
await tester.tap(find.byType(DropdownMenu<TestMenu>));
await tester.pump();
final Finder buttonMaterial = find.descendant(
of: find.widgetWithText(MenuItemButton, 'Item 3'),
matching: find.byType(Material),
).last;
// Validate the item 3 is highlighted.
final Material itemMaterial = tester.widget<Material>(buttonMaterial);
expect(itemMaterial.color, themeData.colorScheme.onSurface.withOpacity(0.12));
});
} }
enum TestMenu { enum TestMenu {
......
...@@ -43,11 +43,11 @@ void main() { ...@@ -43,11 +43,11 @@ void main() {
theme: themeData, theme: themeData,
home: const Scaffold( home: const Scaffold(
body: Center( body: Center(
child: DropdownMenu( child: DropdownMenu<int>(
dropdownMenuEntries: <DropdownMenuEntry>[ dropdownMenuEntries: <DropdownMenuEntry<int>>[
DropdownMenuEntry(label: 'Item 0'), DropdownMenuEntry<int>(value: 0, label: 'Item 0'),
DropdownMenuEntry(label: 'Item 1'), DropdownMenuEntry<int>(value: 1, label: 'Item 1'),
DropdownMenuEntry(label: 'Item 2'), DropdownMenuEntry<int>(value: 2, label: 'Item 2'),
], ],
), ),
), ),
...@@ -122,11 +122,11 @@ void main() { ...@@ -122,11 +122,11 @@ void main() {
theme: theme, theme: theme,
home: const Scaffold( home: const Scaffold(
body: Center( body: Center(
child: DropdownMenu( child: DropdownMenu<int>(
dropdownMenuEntries: <DropdownMenuEntry>[ dropdownMenuEntries: <DropdownMenuEntry<int>>[
DropdownMenuEntry(label: 'Item 0'), DropdownMenuEntry<int>(value: 0, label: 'Item 0'),
DropdownMenuEntry(label: 'Item 1'), DropdownMenuEntry<int>(value: 1, label: 'Item 1'),
DropdownMenuEntry(label: 'Item 2'), DropdownMenuEntry<int>(value: 2, label: 'Item 2'),
], ],
), ),
), ),
...@@ -223,11 +223,11 @@ void main() { ...@@ -223,11 +223,11 @@ void main() {
data: dropdownMenuTheme, data: dropdownMenuTheme,
child: const Scaffold( child: const Scaffold(
body: Center( body: Center(
child: DropdownMenu( child: DropdownMenu<int>(
dropdownMenuEntries: <DropdownMenuEntry>[ dropdownMenuEntries: <DropdownMenuEntry<int>>[
DropdownMenuEntry(label: 'Item 0'), DropdownMenuEntry<int>(value: 0, label: 'Item 0'),
DropdownMenuEntry(label: 'Item 1'), DropdownMenuEntry<int>(value: 1, label: 'Item 1'),
DropdownMenuEntry(label: 'Item 2'), DropdownMenuEntry<int>(value: 2, label: 'Item 2'),
], ],
), ),
), ),
...@@ -326,7 +326,7 @@ void main() { ...@@ -326,7 +326,7 @@ void main() {
data: dropdownMenuTheme, data: dropdownMenuTheme,
child: Scaffold( child: Scaffold(
body: Center( body: Center(
child: DropdownMenu( child: DropdownMenu<int>(
textStyle: TextStyle( textStyle: TextStyle(
color: Colors.pink, color: Colors.pink,
backgroundColor: Colors.cyan, backgroundColor: Colors.cyan,
...@@ -345,10 +345,10 @@ void main() { ...@@ -345,10 +345,10 @@ void main() {
), ),
), ),
inputDecorationTheme: const InputDecorationTheme(filled: true, fillColor: Colors.deepPurple), inputDecorationTheme: const InputDecorationTheme(filled: true, fillColor: Colors.deepPurple),
dropdownMenuEntries: const <DropdownMenuEntry>[ dropdownMenuEntries: const <DropdownMenuEntry<int>>[
DropdownMenuEntry(label: 'Item 0'), DropdownMenuEntry<int>(value: 0, label: 'Item 0'),
DropdownMenuEntry(label: 'Item 1'), DropdownMenuEntry<int>(value: 1, label: 'Item 1'),
DropdownMenuEntry(label: 'Item 2'), DropdownMenuEntry<int>(value: 2, label: 'Item 2'),
], ],
), ),
), ),
......
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