Introduce DropdownMenu.closeBehavior
to control menu closing behavior (#156405)
Fixes [Add option to control whether the root DropdownMenu can be closed or not](https://github.com/flutter/flutter/issues/139269)
This introduces `DropdownMenu.closeBehavior` to provide control over `DropdownMenu` can be closed in nested menus.
### Code sample
<details>
<summary>expand to view the code sample</summary>
```dart
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String selectedValue = "1";
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
spacing: 16.0,
mainAxisSize: MainAxisSize.min,
children: [
const Text("DropdownMenuCloseBehavior.none"),
MenuAnchor(
menuChildren: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownMenu(
closeBehavior: DropdownMenuCloseBehavior.none,
label: const Text('Menu'),
initialSelection: selectedValue,
onSelected: (String? value) {
if (value != null) {
setState(() {
selectedValue = value;
});
}
},
dropdownMenuEntries: ["1", "2", "3"]
.map(
(it) => DropdownMenuEntry(
value: it,
label: it,
),
)
.toList(),
),
)
],
child: const Text('Open Menu'),
builder: (context, controller, child) {
return ElevatedButton(
onPressed: () {
controller.open();
},
child: child,
);
},
),
],
),
Column(
spacing: 16.0,
mainAxisSize: MainAxisSize.min,
children: [
const Text("DropdownMenuCloseBehavior.self"),
MenuAnchor(
menuChildren: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownMenu(
closeBehavior: DropdownMenuCloseBehavior.self,
label: const Text('Menu'),
initialSelection: selectedValue,
onSelected: (String? value) {
if (value != null) {
setState(() {
selectedValue = value;
});
}
},
dropdownMenuEntries: ["1", "2", "3"]
.map(
(it) => DropdownMenuEntry(
value: it,
label: it,
),
)
.toList(),
),
)
],
child: const Text('Open Menu'),
builder: (context, controller, child) {
return ElevatedButton(
onPressed: () {
controller.open();
},
child: child,
);
},
),
],
),
Column(
spacing: 16.0,
mainAxisSize: MainAxisSize.min,
children: [
const Text("DropdownMenuCloseBehavior.all"),
MenuAnchor(
menuChildren: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownMenu(
closeBehavior: DropdownMenuCloseBehavior.all,
label: const Text('Menu'),
initialSelection: selectedValue,
onSelected: (String? value) {
if (value != null) {
setState(() {
selectedValue = value;
});
}
},
dropdownMenuEntries: ["1", "2", "3"]
.map(
(it) => DropdownMenuEntry(
value: it,
label: it,
),
)
.toList(),
),
)
],
child: const Text('Open Menu'),
builder: (context, controller, child) {
return ElevatedButton(
onPressed: () {
controller.open();
},
child: child,
);
},
),
],
),
],
),
),
),
);
}
}
```
</details>
### Demo
https://github.com/user-attachments/assets/1f79ea6e-c0c6-4dcf-8180-d9dcca1c22c5