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.
This commit is contained in:
Bruno Leroux 2024-06-12 10:47:07 +02:00 committed by GitHub
parent ad462e2783
commit fdb74fd3e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 10 deletions

View File

@ -655,7 +655,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
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<T> extends State<DropdownMenu<T>> {
void handleUpKeyInvoke(_) {
setState(() {
if (!_menuHasEnabledItem || !_controller.isOpen) {
if (!widget.enabled || !_menuHasEnabledItem || !_controller.isOpen) {
return;
}
_enableFilter = false;
@ -695,7 +695,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
void handleDownKeyInvoke(_) {
setState(() {
if (!_menuHasEnabledItem || !_controller.isOpen) {
if (!widget.enabled || !_menuHasEnabledItem || !_controller.isOpen) {
return;
}
_enableFilter = false;
@ -786,7 +786,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
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<T> extends State<DropdownMenu<T>> {
final Widget textField = TextField(
key: _anchorKey,
enabled: widget.enabled,
mouseCursor: effectiveMouseCursor,
focusNode: widget.focusNode,
canRequestFocus: canRequestFocus(),
@ -825,7 +826,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
}
controller.close();
},
onTap: () {
onTap: !widget.enabled ? null : () {
handlePressed(controller);
},
onChanged: (String text) {
@ -837,7 +838,6 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
},
inputFormatters: widget.inputFormatters,
decoration: InputDecoration(
enabled: widget.enabled,
label: widget.label,
hintText: widget.hintText,
helperText: widget.helperText,

View File

@ -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<TestMenu>(
@ -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<TestMenu>(
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 {