A Flutter package providing a highly customizable circular/radial context menu, similar to Pinterest's.
Click here to try Flutter Pie Menu online!
Wrap the widget that should respond to gestures with the PieMenu
widget, and provide the menu with an array of PieAction
s to display as circular buttons.
PieMenu(
onPressed: () => print('pressed'),
actions: [
PieAction(
tooltip: const Text('like'),
onSelect: () => print('liked'),
child: const Icon(Icons.favorite), // Can be any widget
),
],
child: ChildWidget(),
),
💡 Don't forget that you can only use
PieMenu
as a descendant of aPieCanvas
widget.
Wrap your page, or any other desired widget for drawing the menu and the background overlay, with PieCanvas
widget.
For instance, if you want the menu to be displayed at the forefront, wrap your Scaffold
with a PieCanvas
like following:
PieCanvas(
child: Scaffold(
body: YourScaffoldBody(
...
PieMenu(),
...
),
),
),
💡 You can utilize the
onPressed
callback defined inPieMenu
to manage tap events without the need for an extra widget such asGestureDetector
.
You can customize the appearance and behavior of menus using PieTheme
.
Using the theme
attribute of PieCanvas
widget, you can specify a theme for all the descendant PieMenu
widgets.
PieCanvas(
theme: PieTheme(),
...
PieMenu(), // Uses the canvas theme
...
PieMenu(), // Uses the canvas theme
...
),
But if you want to specify menu specific themes, you can also use the theme
attribute of PieMenu
widget.
PieMenu(
theme: PieTheme(), // Overrides the canvas theme
),
It is also possible to copy the canvas theme with additional parameters, but make sure you are accessing it with the right context
.
PieMenu(
theme: PieTheme.of(context).copyWith(
...
),
),
Buttons' background and icon colors are defined by theme's buttonTheme
and buttonThemeHovered
. You can create a custom PieButtonTheme
instances for your canvas and menu themes.
PieTheme(
buttonTheme: PieButtonTheme(),
buttonThemeHovered: PieButtonTheme(),
),
You can even give the buttons custom styles using decoration
property of PieButtonTheme
.
PieButtonTheme(
decoration: BoxDecoration(),
),
If you wish to use custom widgets inside buttons instead of just icons, it is recommended to use PieAction.builder()
with a builder
which provides whether the action is hovered or not as a parameter.
PieAction.builder(
tooltip: const Text('like'),
onSelect: () => print('liked'),
builder: (hovered) {
return Text(
'<3',
style: TextStyle(
color: hovered ? Colors.green : Colors.red,
),
);
},
),
If you don't want the dynamic angle calculation and have the menu appear at a fixed angle, set customAngle
and customAngleAnchor
attributes of PieTheme
.
PieTheme(
customAngle: 90, // In degrees
customAngleAnchor: PieAnchor.center, // start, center, end
),
You can also use customAngleDiff
or spacing
to adjust the angle between buttons, and angleOffset
to rotate the menu.
Use menuAlignment
attribute of PieTheme
to make the menu appear at a specific position regardless of the pressed point. Combine it with menuDisplacement
to fine-tune the position.
PieTheme(
menuAlignment: Alignment.center,
menuDisplacement: Offset(0, 0),
),
Set delayDuration
of your theme to Duration.zero
to open the menu instantly on tap.
PieTheme(
delayDuration: Duration.zero,
),
Using rightClickShowsMenu
and leftClickShowsMenu
attributes of PieTheme
, you can customize the mouse button behavior.
PieTheme(
rightClickShowsMenu: true,
leftClickShowsMenu: false,
),
To open, close or toggle a menu programmatically, assign a PieMenuController
to it.
// Create a controller inside a stateful widget.
final _pieMenuController = PieMenuController();
// Assign the controller to a PieMenu.
PieMenu(
controller: _pieMenuController,
...
),
// Control the menu using the controller.
_pieMenuController.open(
menuAlignment: Alignment.center,
);
If you need to do something when the menu is toggled, use onToggle
callback of PieMenu
, or onMenuToggle
callback of PieCanvas
.
PieMenu(
onToggle: (menuOpen) => print('Menu ${menuOpen ? 'opened' : 'closed'}'),
...
),
PieCanvas(
onMenuToggle: (menuOpen) => print('A menu ${menuOpen ? 'opened' : 'closed'}'),
...
),
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
If you find this package useful, please consider donating to support the project.