Reputation: 5827
I have an "add" floating action button in Scaffold. When clicking the "add" floating action button, it will create two more floating action buttons above the original floating action button so that the user can choose which floating action button to click.
When the two more floating action buttons are active/popup, I want the entire screen to go blur/dark and inactive, similar to the effect to call showDialog()
. So that only the three floating action buttons are active and all other screen parts are inactive and dark/blur.
And finally by clicking the inactive area, the two floating action buttons will be dismissed.
Upvotes: 1
Views: 2601
Reputation: 5827
I found two ways to achieve this.
I read flutter framework code and found out showDialog
is actually using PopupRoute
. Basically, this will create a new route and make the previous routepage inactive.
The simplest code is as follows:
class MyPopupRoute extends PopupRoute<void> {
@override
Color get barrierColor => Colors.black54;
@override
bool get barrierDismissible => true;
@override
String get barrierLabel => "Close";
@override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) => MyPopupPage();
@override
Duration get transitionDuration => const Duration(milliseconds: 300);
}
where MyPopupPage
is the new popup widget.
If you want animations, you can override the method buildTransitions
method. Simply check the API doc for more detail.
Thank @01leo very much for providing this way. The Flutter Challenge: Feature Discovery video has detail explanation on how to use it. Basically, just use Overlay.of(context).insert(overlayEntry);
and the overlay is like a hidden stack on the top of the current page built-in.
At the time I am writing this answer, the code provided by the video author is not working in the latest fluter (dart 2). You have to wrap the overlay insert in a Timer such as Timer.run(() { Overlay.of(context).insert(calendarOverlay);});
to workaround the problem and make the code run.
By my findings, the reason why the author needs an async function call for overlay insert is because it couples the creation of overlay and the normal widget in a stateful widget. And when the state changes, the overlay insert will be called before building the child's widget and overlay needs to know the child's position but the child's widget is not created yet. If you don't want to async call overlay insert, you can simply decouple the creation of overlay and the corresponding normal widget. In such a way, you can simply call overlay insert normally. But with this sync way, you may not be able to find the normal widget position easily though. (Btw, I use the word "normal widget" here, but it's not very correct. I haven't found a proper English word for it.)
Upvotes: 4
Reputation: 5780
I can't provide any code, but showDialog()
and similar methods use the Overlay
, integrated in Scaffold
. It can be accessed by using Overlay.of(context)
. It essentially is a Stack
around the whole Scaffold
and you can insert items on top of everything.
For a more in-depth look into the Overlay
and code examples I recommend watching this Flutter Challenge: Feature Discovery
Upvotes: 2