mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add option to hide trailing icon in DropdownMenu (#167782)
This PR adds support for hiding the trailing icon in `DropdownMenu` widget. Currently, there's no built-in option to remove it. The change is non-breaking, as the trailing icon remains visible by default unless `showTrailingIcon` is explicitly set to `false`. The `showTrailingIcon` parameter follows a similar pattern to its use in the `ExpansionTile` widget. Fixes #164908 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. --------- Co-authored-by: Qun Cheng <36861262+QuncCccccc@users.noreply.github.com>
This commit is contained in:
parent
3a1c297206
commit
930d21504a
@ -164,6 +164,7 @@ class DropdownMenu<T> extends StatefulWidget {
|
||||
this.menuHeight,
|
||||
this.leadingIcon,
|
||||
this.trailingIcon,
|
||||
this.showTrailingIcon = true,
|
||||
this.label,
|
||||
this.hintText,
|
||||
this.helperText,
|
||||
@ -225,8 +226,18 @@ class DropdownMenu<T> extends StatefulWidget {
|
||||
/// An optional icon at the end of the text field.
|
||||
///
|
||||
/// Defaults to an [Icon] with [Icons.arrow_drop_down].
|
||||
///
|
||||
/// If [showTrailingIcon] is false, the trailing icon will not be shown.
|
||||
final Widget? trailingIcon;
|
||||
|
||||
/// Specifies if the [DropdownMenu] should show a [trailingIcon].
|
||||
///
|
||||
/// If [trailingIcon] is set, [DropdownMenu] will use that trailing icon,
|
||||
/// otherwise a default trailing icon will be created.
|
||||
///
|
||||
/// Defaults to true.
|
||||
final bool showTrailingIcon;
|
||||
|
||||
/// Optional widget that describes the input field.
|
||||
///
|
||||
/// When the input field is empty and unfocused, the label is displayed on
|
||||
@ -1008,22 +1019,25 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
|
||||
builder: (BuildContext context, MenuController controller, Widget? child) {
|
||||
assert(_initialMenu != null);
|
||||
final bool isCollapsed = widget.inputDecorationTheme?.isCollapsed ?? false;
|
||||
final Widget trailingButton = Padding(
|
||||
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:
|
||||
!widget.enabled
|
||||
? null
|
||||
: () {
|
||||
handlePressed(controller);
|
||||
},
|
||||
),
|
||||
);
|
||||
final Widget trailingButton =
|
||||
widget.showTrailingIcon
|
||||
? Padding(
|
||||
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:
|
||||
!widget.enabled
|
||||
? null
|
||||
: () {
|
||||
handlePressed(controller);
|
||||
},
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink();
|
||||
|
||||
final Widget leadingButton = Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
@ -1070,7 +1084,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
|
||||
widget.leadingIcon != null
|
||||
? SizedBox(key: _leadingKey, child: widget.leadingIcon)
|
||||
: null,
|
||||
suffixIcon: trailingButton,
|
||||
suffixIcon: widget.showTrailingIcon ? trailingButton : null,
|
||||
).applyDefaults(effectiveInputDecorationTheme),
|
||||
restorationId: widget.restorationId,
|
||||
);
|
||||
|
||||
@ -4238,6 +4238,47 @@ void main() {
|
||||
final TextField textField = tester.firstWidget(find.byType(TextField));
|
||||
expect(textField.restorationId, restorationId);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'DropdownMenu does not include the default trailing icon when showTrailingIcon is false',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: DropdownMenu<TestMenu>(
|
||||
showTrailingIcon: false,
|
||||
dropdownMenuEntries: menuChildren,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pump();
|
||||
|
||||
final Finder iconButton = find.widgetWithIcon(IconButton, Icons.arrow_drop_down);
|
||||
expect(iconButton, findsNothing);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'DropdownMenu does not include the provided trailing icon when showTrailingIcon is false',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: DropdownMenu<TestMenu>(
|
||||
trailingIcon: const Icon(Icons.ac_unit),
|
||||
showTrailingIcon: false,
|
||||
dropdownMenuEntries: menuChildren,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pump();
|
||||
|
||||
final Finder iconButton = find.widgetWithIcon(IconButton, Icons.ac_unit);
|
||||
expect(iconButton, findsNothing);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
enum TestMenu {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user