mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 22:09:06 +00:00
Add a menu example to show menu system (#1578)
This commit is contained in:
@@ -179,14 +179,11 @@ class _ButtonsState extends State<Buttons> {
|
|||||||
'Use ElevatedButton, FilledButton, FilledButton.tonal, OutlinedButton, or TextButton',
|
'Use ElevatedButton, FilledButton, FilledButton.tonal, OutlinedButton, or TextButton',
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: tinySpacing),
|
child: Row(
|
||||||
child: Column(
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: const <Widget>[
|
children: const <Widget>[
|
||||||
ButtonsWithoutIcon(isDisabled: false),
|
ButtonsWithoutIcon(isDisabled: false),
|
||||||
colDivider,
|
|
||||||
ButtonsWithIcon(),
|
ButtonsWithIcon(),
|
||||||
colDivider,
|
|
||||||
ButtonsWithoutIcon(isDisabled: true),
|
ButtonsWithoutIcon(isDisabled: true),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -202,33 +199,39 @@ class ButtonsWithoutIcon extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return Padding(
|
||||||
children: <Widget>[
|
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
ElevatedButton(
|
child: IntrinsicWidth(
|
||||||
onPressed: isDisabled ? null : () {},
|
child: Column(
|
||||||
child: const Text('Elevated'),
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: <Widget>[
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: isDisabled ? null : () {},
|
||||||
|
child: const Text('Elevated'),
|
||||||
|
),
|
||||||
|
colDivider,
|
||||||
|
FilledButton(
|
||||||
|
onPressed: isDisabled ? null : () {},
|
||||||
|
child: const Text('Filled'),
|
||||||
|
),
|
||||||
|
colDivider,
|
||||||
|
FilledButton.tonal(
|
||||||
|
onPressed: isDisabled ? null : () {},
|
||||||
|
child: const Text('Filled tonal'),
|
||||||
|
),
|
||||||
|
colDivider,
|
||||||
|
OutlinedButton(
|
||||||
|
onPressed: isDisabled ? null : () {},
|
||||||
|
child: const Text('Outlined'),
|
||||||
|
),
|
||||||
|
colDivider,
|
||||||
|
TextButton(
|
||||||
|
onPressed: isDisabled ? null : () {},
|
||||||
|
child: const Text('Text'),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: tinySpacing),
|
),
|
||||||
FilledButton(
|
|
||||||
onPressed: isDisabled ? null : () {},
|
|
||||||
child: const Text('Filled'),
|
|
||||||
),
|
|
||||||
const SizedBox(width: tinySpacing),
|
|
||||||
FilledButton.tonal(
|
|
||||||
onPressed: isDisabled ? null : () {},
|
|
||||||
child: const Text('Filled tonal'),
|
|
||||||
),
|
|
||||||
const SizedBox(width: tinySpacing),
|
|
||||||
OutlinedButton(
|
|
||||||
onPressed: isDisabled ? null : () {},
|
|
||||||
child: const Text('Outlined'),
|
|
||||||
),
|
|
||||||
const SizedBox(width: tinySpacing),
|
|
||||||
TextButton(
|
|
||||||
onPressed: isDisabled ? null : () {},
|
|
||||||
child: const Text('Text'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,38 +241,44 @@ class ButtonsWithIcon extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return Padding(
|
||||||
children: <Widget>[
|
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||||
ElevatedButton.icon(
|
child: IntrinsicWidth(
|
||||||
onPressed: () {},
|
child: Column(
|
||||||
icon: const Icon(Icons.add),
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
label: const Text('Icon'),
|
children: <Widget>[
|
||||||
|
ElevatedButton.icon(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
label: const Text('Icon'),
|
||||||
|
),
|
||||||
|
colDivider,
|
||||||
|
FilledButton.icon(
|
||||||
|
onPressed: () {},
|
||||||
|
label: const Text('Icon'),
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
),
|
||||||
|
colDivider,
|
||||||
|
FilledButton.tonalIcon(
|
||||||
|
onPressed: () {},
|
||||||
|
label: const Text('Icon'),
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
),
|
||||||
|
colDivider,
|
||||||
|
OutlinedButton.icon(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
label: const Text('Icon'),
|
||||||
|
),
|
||||||
|
colDivider,
|
||||||
|
TextButton.icon(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
label: const Text('Icon'),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: tinySpacing),
|
),
|
||||||
FilledButton.icon(
|
|
||||||
onPressed: () {},
|
|
||||||
label: const Text('Icon'),
|
|
||||||
icon: const Icon(Icons.add),
|
|
||||||
),
|
|
||||||
const SizedBox(width: tinySpacing),
|
|
||||||
FilledButton.tonalIcon(
|
|
||||||
onPressed: () {},
|
|
||||||
label: const Text('Icon'),
|
|
||||||
icon: const Icon(Icons.add),
|
|
||||||
),
|
|
||||||
const SizedBox(width: tinySpacing),
|
|
||||||
OutlinedButton.icon(
|
|
||||||
onPressed: () {},
|
|
||||||
icon: const Icon(Icons.add),
|
|
||||||
label: const Text('Icon'),
|
|
||||||
),
|
|
||||||
const SizedBox(width: tinySpacing),
|
|
||||||
TextButton.icon(
|
|
||||||
onPressed: () {},
|
|
||||||
icon: const Icon(Icons.add),
|
|
||||||
label: const Text('Icon'),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1516,10 +1525,7 @@ class BottomAppBars extends StatelessWidget {
|
|||||||
bottomNavigationBar: BottomAppBar(
|
bottomNavigationBar: BottomAppBar(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
IconButton(
|
const IconButtonAnchorExample(),
|
||||||
icon: const Icon(Icons.more_vert),
|
|
||||||
onPressed: () {},
|
|
||||||
),
|
|
||||||
IconButton(
|
IconButton(
|
||||||
tooltip: 'Search',
|
tooltip: 'Search',
|
||||||
icon: const Icon(Icons.search),
|
icon: const Icon(Icons.search),
|
||||||
@@ -1541,6 +1547,94 @@ class BottomAppBars extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class IconButtonAnchorExample extends StatelessWidget {
|
||||||
|
const IconButtonAnchorExample({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MenuAnchor(
|
||||||
|
builder: (context, controller, child) {
|
||||||
|
return IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (controller.isOpen) {
|
||||||
|
controller.close();
|
||||||
|
} else {
|
||||||
|
controller.open();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.more_vert),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
menuChildren: [
|
||||||
|
MenuItemButton(
|
||||||
|
child: const Text('Menu 1'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
child: const Text('Menu 2'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
SubmenuButton(
|
||||||
|
menuChildren: <Widget>[
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: const Text('Menu 3.1'),
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: const Text('Menu 3.2'),
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: const Text('Menu 3.3'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: const Text('Menu 3'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ButtonAnchorExample extends StatelessWidget {
|
||||||
|
const ButtonAnchorExample({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MenuAnchor(
|
||||||
|
builder: (context, controller, child) {
|
||||||
|
return FilledButton.tonal(
|
||||||
|
onPressed: () {
|
||||||
|
if (controller.isOpen) {
|
||||||
|
controller.close();
|
||||||
|
} else {
|
||||||
|
controller.open();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const Text('Show menu'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
menuChildren: [
|
||||||
|
MenuItemButton(
|
||||||
|
leadingIcon: const Icon(Icons.people_alt_outlined),
|
||||||
|
child: const Text('Item 1'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
leadingIcon: const Icon(Icons.remove_red_eye_outlined),
|
||||||
|
child: const Text('Item 2'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
leadingIcon: const Icon(Icons.refresh),
|
||||||
|
onPressed: () {},
|
||||||
|
child: const Text('Item 3'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class NavigationDrawers extends StatelessWidget {
|
class NavigationDrawers extends StatelessWidget {
|
||||||
const NavigationDrawers({super.key, required this.scaffoldKey});
|
const NavigationDrawers({super.key, required this.scaffoldKey});
|
||||||
final GlobalKey<ScaffoldState> scaffoldKey;
|
final GlobalKey<ScaffoldState> scaffoldKey;
|
||||||
@@ -1727,43 +1821,59 @@ class _DropdownMenusState extends State<DropdownMenus> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ComponentDecoration(
|
return ComponentDecoration(
|
||||||
label: 'Dropdown menus',
|
label: 'Menus',
|
||||||
tooltipMessage: 'Use DropdownMenu<T>',
|
tooltipMessage: 'Use DropdownMenu<T> or MenuAnchor',
|
||||||
child: Wrap(
|
child: Column(
|
||||||
alignment: WrapAlignment.spaceAround,
|
mainAxisSize: MainAxisSize.min,
|
||||||
runAlignment: WrapAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: WrapCrossAlignment.center,
|
|
||||||
spacing: smallSpacing,
|
|
||||||
runSpacing: smallSpacing,
|
|
||||||
children: [
|
children: [
|
||||||
DropdownMenu<ColorLabel>(
|
Row(
|
||||||
controller: colorController,
|
mainAxisSize: MainAxisSize.min,
|
||||||
label: const Text('Color'),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
enableFilter: true,
|
children: const <Widget>[
|
||||||
dropdownMenuEntries: colorEntries,
|
ButtonAnchorExample(),
|
||||||
inputDecorationTheme: const InputDecorationTheme(filled: true),
|
rowDivider,
|
||||||
onSelected: (color) {
|
IconButtonAnchorExample(),
|
||||||
setState(() {
|
],
|
||||||
selectedColor = color;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
DropdownMenu<IconLabel>(
|
colDivider,
|
||||||
initialSelection: IconLabel.smile,
|
Wrap(
|
||||||
controller: iconController,
|
alignment: WrapAlignment.spaceAround,
|
||||||
leadingIcon: const Icon(Icons.search),
|
runAlignment: WrapAlignment.start,
|
||||||
label: const Text('Icon'),
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
dropdownMenuEntries: iconEntries,
|
spacing: smallSpacing,
|
||||||
onSelected: (icon) {
|
runSpacing: smallSpacing,
|
||||||
setState(() {
|
children: [
|
||||||
selectedIcon = icon;
|
DropdownMenu<ColorLabel>(
|
||||||
});
|
controller: colorController,
|
||||||
},
|
label: const Text('Color'),
|
||||||
|
enableFilter: true,
|
||||||
|
dropdownMenuEntries: colorEntries,
|
||||||
|
inputDecorationTheme: const InputDecorationTheme(filled: true),
|
||||||
|
onSelected: (color) {
|
||||||
|
setState(() {
|
||||||
|
selectedColor = color;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
DropdownMenu<IconLabel>(
|
||||||
|
initialSelection: IconLabel.smile,
|
||||||
|
controller: iconController,
|
||||||
|
leadingIcon: const Icon(Icons.search),
|
||||||
|
label: const Text('Icon'),
|
||||||
|
dropdownMenuEntries: iconEntries,
|
||||||
|
onSelected: (icon) {
|
||||||
|
setState(() {
|
||||||
|
selectedIcon = icon;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
selectedIcon?.icon,
|
||||||
|
color: selectedColor?.color ?? Colors.grey.withOpacity(0.5),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Icon(
|
|
||||||
selectedIcon?.icon,
|
|
||||||
color: selectedColor?.color ?? Colors.grey.withOpacity(0.5),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user