I am trying to make an overlay such as that shown here:
https://www.didierboelens.com/2018/06/how-to-create-a-toast-or-notifications-notion-of-overlay/
using OverlayEntry
.
import 'package:flutter/material.dart';
import 'dart:async';
class ShowNotificationIcon {
void show(BuildContext context) async {
OverlayState overlayState = Overlay.of(context);
OverlayEntry overlayEntry = new OverlayEntry(builder: _build);
overlayState.insert(overlayEntry);
}
Widget _build(BuildContext context){
return new Positioned(
top: 50.0,
left: 50.0,
child: new Material(
color: Colors.transparent,
child: new Icon(Icons.warning, color: Colors.purple),
),
);
}
}
Invoked with:
ShowNotificationIcon _icon = new ShowNotificationIcon();
_icon.show(context);
However, when I try to navigate to other screens, the overlay remains in the screen.
How do I show the overlay only in the screen it is being called and not in the others?
Just in case, this is what I had tried inside my stateful widget:
ShowNotificationIcon _icon = new ShowNotificationIcon();
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
_icon.show(context);
});
super.initState();
}
@override
void dispose() {
_icon.remove();
super.dispose();
}
This is typically performed using RouteAware
+RouteObserver
.
RouteObserver
is an object that lets objects that implements RouteAware
react to some changes related to routing, which includes:
You can then use these two events to hide/show your overlay
First, you'll need a RouteObserver
.
This can be created as a global variable and needs to be passed to your Navigator
. In a MaterialApp
based app, it'll typically look like this:
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
void main() {
runApp(MaterialApp(
home: Container(),
navigatorObservers: [routeObserver],
));
}
Then, your widget that owns the OverlayEntry
can now implement RouteAware
like so:
class RouteAwareWidget extends StatefulWidget {
State<RouteAwareWidget> createState() => RouteAwareWidgetState();
}
// Implement RouteAware in a widget's state and subscribe it to the RouteObserver.
class RouteAwareWidgetState extends State<RouteAwareWidget> with RouteAware {
@override
void didChangeDependencies() {
super.didChangeDependencies();
// routeObserver is the global variable we created before
routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute);
}
@override
void dispose() {
routeObserver.unsubscribe(this);
super.dispose();
}
@override
void didPush() {
// Route was pushed onto navigator and is now topmost route.
}
@override
void didPopNext() {
// Covering route was popped off the navigator.
}
@override
Widget build(BuildContext context) => Container();
}
At this point, you can use didPush
and didPopNext
to show/hide your OverlayEntry:
OverlayEntry myOverlay;
@override
void didPush() {
myOverlay.remove();
}
@override
void didPopNext() {
Overlay.of(context).insert(myOverlay);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With