Reputation: 1000
In my app, it is possible (and intended!) that multiple SnackBar
elements are created. These SnackBar
elements are queued and displayed one after another which is all well and fine. However, if I go to a different screen and then go back (so push
and pop
a route) all SnackBar
elements are still there.
So I would like to remove all SnackBar
s upon pushing a route.
I tried counting my SnackBar
elements and calling scaffoldKey.currentState.removeCurrentSnackBar()
that many times in the following locations:
before Navigator.push()
which works, however, since I have multiple points where I push something I would like to use some callback.
in didPushRoute()
from WidgetsBindingObserver
, however, even after registering the observer, this method is never called. (ChangeAppLifecycleState()
is called so the registering seems to be not completely wrong?)
in dispose()
. This actually produces my intended behavior but throws exceptions from AnimatedBuilder
(Exception text: "setState() or markNeedsBuild() called during build.
"), which I would like to avoid, even if the animation library seems to catch those.
If everything fails, I suppose I could just wrap Navigator.push()
in a helper function that also clears the SnackBar
queue but I hoped that there would be a more elegant way.
Upvotes: 8
Views: 5767
Reputation: 6362
To clear all SnackBar
s, there is a ScaffoldMessenger.of(context).clearSnackBars()
method which can be used in your pushNamed
wrapper. :-)
Upvotes: 8
Reputation: 4854
You can use this to remove Snackbar in Flutetr2
ScaffoldMessenger.of(context).removeCurrentSnackBar();
Example code
onPressed: () {
ScaffoldMessenger.of(context).removeCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('New Snackbar'),
),
);
}
Upvotes: 11
Reputation: 1000
So, in the end, I ended up writing the following function and call it everywhere instead of Navigator.pushNamed()
Future<T> _pushNamedWrapper<T extends Object>(
BuildContext context,
String routeName, {
Object arguments,
}) {
for (int snackbarsLeft = _snackbarCounter;
snackbarsLeft > 0;
snackbarsLeft = snackbarsLeft - 1) {
_scaffoldKey.currentState.removeCurrentSnackBar();
}
return Navigator.pushNamed(context, routeName, arguments: arguments);
}
here, _snackbarCounter
is a counter var that will be incremented whenever a snack bar is created or decremented as soon as it disappears. Roughly like this:
// function where you want your snackbar to be triggered
() {
_snackbarCounter = _snackbarCounter + 1;
Scaffold.of(context)
.showSnackBar(SnackBar(
content: // your content...
))
.closed
.then((SnackBarClosedReason reason) =>
_snackbarCounter = _snackbarCounter - 1);
}
Upvotes: 0