From fdb74fd3e7e08d99d8e19a0d7c548cf6cab56b31 Mon Sep 17 00:00:00 2001 From: Bruno Leroux Date: Wed, 12 Jun 2024 10:47:07 +0200 Subject: [PATCH] Fix DropdownMenu can be focused and updated when disabled (#149737) ## Description This PRs fixes `DropdownMenu` behaviors when disabled. Before this PR the `DropdownMenu` value can be changed when `DropdownMenu.enabled` was false because the inner `IconButton` was not disabled so it can get focus (for instance using tab key). After this PR, the inner `TextField` and the inner `IconButton` are disabled when `DropdownMenu.enabled` is false. ## Related Issue Fixes https://github.com/flutter/flutter/issues/149598. ## Tests Updates 1 test. Adds 1 test. --- .../lib/src/material/dropdown_menu.dart | 12 ++++----- .../test/material/dropdown_menu_test.dart | 25 ++++++++++++++++--- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/packages/flutter/lib/src/material/dropdown_menu.dart b/packages/flutter/lib/src/material/dropdown_menu.dart index 8073004696..7e634cd2aa 100644 --- a/packages/flutter/lib/src/material/dropdown_menu.dart +++ b/packages/flutter/lib/src/material/dropdown_menu.dart @@ -655,7 +655,7 @@ class _DropdownMenuState extends State> { style: effectiveStyle, leadingIcon: entry.leadingIcon, trailingIcon: entry.trailingIcon, - onPressed: entry.enabled + onPressed: entry.enabled && widget.enabled ? () { _localTextEditingController?.value = TextEditingValue( text: entry.label, @@ -676,7 +676,7 @@ class _DropdownMenuState extends State> { void handleUpKeyInvoke(_) { setState(() { - if (!_menuHasEnabledItem || !_controller.isOpen) { + if (!widget.enabled || !_menuHasEnabledItem || !_controller.isOpen) { return; } _enableFilter = false; @@ -695,7 +695,7 @@ class _DropdownMenuState extends State> { void handleDownKeyInvoke(_) { setState(() { - if (!_menuHasEnabledItem || !_controller.isOpen) { + if (!widget.enabled || !_menuHasEnabledItem || !_controller.isOpen) { return; } _enableFilter = false; @@ -786,7 +786,7 @@ class _DropdownMenuState extends State> { isSelected: controller.isOpen, icon: widget.trailingIcon ?? const Icon(Icons.arrow_drop_down), selectedIcon: widget.selectedTrailingIcon ?? const Icon(Icons.arrow_drop_up), - onPressed: () { + onPressed: !widget.enabled ? null : () { handlePressed(controller); }, ), @@ -799,6 +799,7 @@ class _DropdownMenuState extends State> { final Widget textField = TextField( key: _anchorKey, + enabled: widget.enabled, mouseCursor: effectiveMouseCursor, focusNode: widget.focusNode, canRequestFocus: canRequestFocus(), @@ -825,7 +826,7 @@ class _DropdownMenuState extends State> { } controller.close(); }, - onTap: () { + onTap: !widget.enabled ? null : () { handlePressed(controller); }, onChanged: (String text) { @@ -837,7 +838,6 @@ class _DropdownMenuState extends State> { }, inputFormatters: widget.inputFormatters, decoration: InputDecoration( - enabled: widget.enabled, label: widget.label, hintText: widget.hintText, helperText: widget.helperText, diff --git a/packages/flutter/test/material/dropdown_menu_test.dart b/packages/flutter/test/material/dropdown_menu_test.dart index 17901fb2e0..e9f84e1b0c 100644 --- a/packages/flutter/test/material/dropdown_menu_test.dart +++ b/packages/flutter/test/material/dropdown_menu_test.dart @@ -83,11 +83,9 @@ void main() { expect(material.textStyle?.height, 1.43); }); - testWidgets('DropdownMenu can be disabled', (WidgetTester tester) async { - final ThemeData themeData = ThemeData(); + testWidgets('Inner TextField is disabled when DropdownMenu is disabled', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( - theme: themeData, home: Scaffold( body: SafeArea( child: DropdownMenu( @@ -100,7 +98,7 @@ void main() { ); final TextField textField = tester.widget(find.byType(TextField)); - expect(textField.decoration?.enabled, false); + expect(textField.enabled, false); final Finder menuMaterial = find.ancestor( of: find.byType(SingleChildScrollView), matching: find.byType(Material), @@ -116,6 +114,25 @@ void main() { expect(updatedMenuMaterial, findsNothing); }); + testWidgets('Inner IconButton is disabled when DropdownMenu is disabled', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/149598. + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: SafeArea( + child: DropdownMenu( + enabled: false, + dropdownMenuEntries: menuChildren, + ), + ), + ), + ), + ); + + final IconButton trailingButton = tester.widget(find.widgetWithIcon(IconButton, Icons.arrow_drop_down).first); + expect(trailingButton.onPressed, null); + }); + testWidgets('Material2 - The width of the text field should always be the same as the menu view', (WidgetTester tester) async {