How not to dismiss a PopUpMenuButton after selecting an item?
Solution 1
Create a custom class, say PopupItem
, which extends PopupMenuItem
and override PopupMenuItemState.handleTap
method.
class PopupItem extends PopupMenuItem {
const PopupItem({
required Widget child,
Key? key,
}) : super(key: key, child: child);
@override
_PopupItemState createState() => _PopupItemState();
}
class _PopupItemState extends PopupMenuItemState {
@override
void handleTap() {}
}
You can now use it like this:
PopupMenuButton(
itemBuilder: (_) {
return [
PopupItem(child: ...),
];
},
)
Solution 2
So I had a requirement where I had to
create a form field with a drop-down menu with checkable items
So I created a popup menu with PopupMenuItem but then I had 3 problems
- When an item was selected popup was getting dismissed
- Clicking on the checkbox was not updating the checkbox state
- Clicking on the text was not updating the check box
So I solved all these issues like this, this may help you guys
- Set enabled = false in PopupMenuItem and Wrapped the child with a gesture listener for click listeners
- Used StatefulBuilder to update the state
- Solution 1 solved this problem too
Here is the code ->
onTapDown: (details) async {
state.didChange(
await showMenu(
context: context,
position: RelativeRect.fromLTRB(
details.globalPosition.dx,
details.globalPosition.dy,
0,
0,
),
items: itemList.keys
.map(
(e) => PopupMenuItem(
enabled: false,
child: StatefulBuilder(
builder: (BuildContext context,
StateSetter setState) {
return GestureDetector(
onTap: () {
setState(() {
itemList[e] = !itemList[e]!;
});
},
child: Row(
children: [
Expanded(child: Text(e)),
Checkbox(
value: itemList[e],
onChanged: (i) {
setState(() {
itemList[e] = i!;
});
},
),
],
),
);
},
),
),
)
.toList(),
elevation: 8.0,
).then((value) => null) ??
[],
);
}
Solution 3
@Omi,
I had faced similar situation... wanted a Popup but didn't want it to be dismissed when I select a PopupMenuItem.
I had implemented this :
enabled → bool Whether the user is permitted to select this item. [...]
I have set enabled to false for the menu item (In my case it was a card having my custom UI)
Solution 4
You can use CheckedPopupMenuItem like this.. as mentioned at Official Documentation
PopupMenuButton<Commands>(
onSelected: (Commands result) {
switch (result) {
case Commands.heroAndScholar:
setState(() { _heroAndScholar = !_heroAndScholar; });
break;
case Commands.hurricaneCame:
// ...handle hurricane option
break;
// ...other items handled here
}
},
itemBuilder: (BuildContext context) => <PopupMenuEntry<Commands>>[
CheckedPopupMenuItem<Commands>(
checked: _heroAndScholar,
value: Commands.heroAndScholar,
child: const Text('Hero and scholar'),
),
const PopupMenuDivider(),
const PopupMenuItem<Commands>(
value: Commands.hurricaneCame,
child: ListTile(leading: Icon(null), title: Text('Bring hurricane')),
),
// ...other items listed here
],
)
Solution 5
You have to modifythe package popupmenubutton. Whenever something is selected in the menu, the menu popped out. So you have to just comment out the Navigator.pop() in the main file of this widget.
comment out the
Navigator.pop<T>(context, widget.value);
in the the main file.
/// The handler for when the user selects the menu item.
///
/// Used by the [InkWell] inserted by the [build] method.
///
/// By default, uses [Navigator.pop] to return the [PopupMenuItem.value] from
/// the menu route.
@protected
void handleTap() {
widget.onTap?.call();
// Navigator.pop<T>(context, widget.value);
}
Omi
Updated on December 01, 2022Comments
-
Omi over 1 year
I am using flutter PopUpMenuButton. All i want is when i select any item on the menu, the popup should not be dismissed, rather let me select multiple values from the popup.The documentation says that you can override the handleTap property, but it is unclear for me how to do that? This is documented
///The [handleTap] method can be overridden to adjust exactly what happens when /// the item is tapped. By default, it uses [Navigator.pop] to return the /// [PopupMenuItem.value] from the menu route. void handleTap() { Navigator.pop<T>(context, widget.value); }
-
Omi about 4 yearsthis surely works, but i wanted to add a custom radio button with animation, i don't this CheckedPopUpMenu button will allow me to do this. Btw thanks for answering..
-
Jaimil Patel about 4 yearsPlease upvote my answer if it maches according to your questions. i know that you want to implement Radio button instead of CheckedPopupMenu button but for other user it will be usefull
-
Omi about 4 yearsi just tried CheckedPopUpmenu button, it doesnt work either, i don't know why, it just gets ticked and the menu dismissed, i am not able to select multiple value
-
Delmontee almost 3 yearsHow can you use this in a stateful widget, to update the display? For example, a menu with a list of checkboxes. User clicks a checkbox, the value toggles from on/off and it is updated on screen?
-
iDecode almost 3 years@James Surely not something that can be explained in comments.
-
obezyan over 2 years@James You may also override method buildChild() from your custom class extended from PopupMenuItemState and pass null to child field of PopupMenuItem.
-
Rahul Singh over 2 yearsIt works perfectly. But I am facing an issue Text displays in grey color because widget is disabled (I have Displayed Text in pop up menu with Blue color). Is there a way to override disabled behaviour in pop up menu item
-
Awais Abbas over 2 years@RahulSingh did you try to add text style?
-
Rahul Singh over 2 yearsAfter you pointed out that I did and It works. Thanks For the help