diff --git a/packages/flutter/lib/src/material/dropdown_menu.dart b/packages/flutter/lib/src/material/dropdown_menu.dart index dbe43dfe47..c27e496eef 100644 --- a/packages/flutter/lib/src/material/dropdown_menu.dart +++ b/packages/flutter/lib/src/material/dropdown_menu.dart @@ -965,10 +965,13 @@ class _DropdownMenuState extends State> { crossAxisUnconstrained: false, builder: (BuildContext context, MenuController controller, Widget? child) { assert(_initialMenu != null); + final bool isCollapsed = widget.inputDecorationTheme?.isCollapsed ?? false; final Widget trailingButton = Padding( - padding: const EdgeInsets.all(4.0), + padding: isCollapsed ? EdgeInsets.zero : const EdgeInsets.all(4.0), child: IconButton( isSelected: controller.isOpen, + constraints: widget.inputDecorationTheme?.suffixIconConstraints, + padding: isCollapsed ? EdgeInsets.zero : null, icon: widget.trailingIcon ?? const Icon(Icons.arrow_drop_down), selectedIcon: widget.selectedTrailingIcon ?? const Icon(Icons.arrow_drop_up), onPressed: diff --git a/packages/flutter/test/material/dropdown_menu_test.dart b/packages/flutter/test/material/dropdown_menu_test.dart index 78de820f64..0a38c49388 100644 --- a/packages/flutter/test/material/dropdown_menu_test.dart +++ b/packages/flutter/test/material/dropdown_menu_test.dart @@ -46,6 +46,7 @@ void main() { double? menuHeight, Widget? leadingIcon, Widget? label, + InputDecorationTheme? decorationTheme, }) { return MaterialApp( theme: themeData, @@ -56,6 +57,7 @@ void main() { width: width, menuHeight: menuHeight, dropdownMenuEntries: entries, + inputDecorationTheme: decorationTheme, ), ), ); @@ -1172,6 +1174,71 @@ void main() { expect(iconButton, findsOneWidget); }); + testWidgets('Trailing IconButton height respects InputDecorationTheme.suffixIconConstraints', ( + WidgetTester tester, + ) async { + final ThemeData themeData = ThemeData(); + + // Default suffix icon constraints. + await tester.pumpWidget(buildTest(themeData, menuChildren)); + await tester.pump(); + + final Finder iconButton = find.widgetWithIcon(IconButton, Icons.arrow_drop_down).first; + expect(tester.getSize(iconButton), const Size(48, 48)); + + // Custom suffix icon constraints. + await tester.pumpWidget( + buildTest( + themeData, + menuChildren, + decorationTheme: const InputDecorationTheme( + suffixIconConstraints: BoxConstraints(minWidth: 66, minHeight: 62), + ), + ), + ); + await tester.pump(); + + expect(tester.getSize(iconButton), const Size(66, 62)); + }); + + testWidgets('InputDecorationTheme.isCollapsed reduces height', (WidgetTester tester) async { + final ThemeData themeData = ThemeData(); + + // Default height. + await tester.pumpWidget(buildTest(themeData, menuChildren)); + await tester.pump(); + + final Finder textField = find.byType(TextField).first; + expect(tester.getSize(textField).height, 56); + + // Collapsed height. + await tester.pumpWidget( + buildTest( + themeData, + menuChildren, + decorationTheme: const InputDecorationTheme(isCollapsed: true), + ), + ); + await tester.pump(); + + expect(tester.getSize(textField).height, 48); // IconButton min height. + + // Collapsed height with custom suffix icon constraints. + await tester.pumpWidget( + buildTest( + themeData, + menuChildren, + decorationTheme: const InputDecorationTheme( + isCollapsed: true, + suffixIconConstraints: BoxConstraints(maxWidth: 24, maxHeight: 24), + ), + ), + ); + await tester.pump(); + + expect(tester.getSize(textField).height, 24); + }); + testWidgets('Do not crash when resize window during menu opening', (WidgetTester tester) async { addTearDown(tester.view.reset); final ThemeData themeData = ThemeData();