29

After an action (for example, "save"), user is returned to another page in the app.

I want to show a snackbar on the new page to confirm the action, but don't want it to show if the user navigated there without the action. So for example, if user saves "thing", the app sends them to "things" main page and shows the "saved" snackbar, but if they go to "things" main page some other way, I don't want the "saved" snackbar to be there.

Here is my code on the panel that saves, but the destination page does not show the snackbar — regardless where I place the snackbar (before or after navigation), it does not execute the snackbar.

Future<Null> saveThatThing() async { thing.save(); thing = new Thing(); Navigator.of(context).push(getSavedThingRoute()); Scaffold.of(context).showSnackBar( new SnackBar( content: new Text('You saved the thing!'), ), ); } 

What is the best way to do this?

4
  • see stackoverflow.com/a/46108172/918867 . Use Future.delayed at initState in new page. Commented Dec 23, 2017 at 14:37
  • Also take a look at snack_bar_demo github.com/flutter/flutter/blob/master/examples/flutter_gallery/… + Navigator.of().push() returns Future, so you can await it maybe? :/ docs.flutter.io/flutter/widgets/Navigator/push.html Commented Dec 27, 2017 at 22:15
  • I guess you also have the option of showing the snackbar thereby passing your information before navigating to the next screen by adding a delay before Navigator.of(context).push(getSavedThingRoute()) Commented Aug 31, 2018 at 23:08
  • FWIW, you should await that push(). Also, doing this in a StatelessWidget does not work currently. Changing the widget to be stateful worked for me. Commented Dec 3, 2018 at 0:05

8 Answers 8

20

What about if you create key for the screen Scaffold like this (put this object inside the screen state class):

final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>(); 

and then set this variable to the Scaffold key like this:

return new Scaffold( key: scaffoldKey, appBar: new AppBar( ......., ), 

and at the end to show the SnackBar just use somewhere inside the screen state class this code :

scaffoldKey.currentState .showSnackBar(new SnackBar(content: new Text("Hello"))); 

or you can wrap the latest code in method like this :

void showInSnackBar(String value) { scaffoldKey.currentState .showSnackBar(new SnackBar(content: new Text(value)));} 

and then just call this method and pass the snack bar message inside.

If you want to show the snack bar message on the next screen, after you navigate away from the initial context, just call the snack bar method on the next screen, not on the first screen.

Hope this will help

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you @Deborah. I am not sure why was downvoted. If something does not work, pls let me know so I can try to help.
This makes total sense. Why can't the docs be this simple to comprehend? :facepalm
Also make sure this scaffoldKey is not in a StatelessWidget. It will sometimes get recreated and you'll get surprise bugs. It goes into a State<>.
This works, but you have to use WidgetsBinding.instance.addPostFrameCallback in your initState (see this article: didierboelens.com/2019/04/addpostframecallback).
@StoychoAndreev is there any method to set snackbar message on first page and show it on second page after redirection from first page to second page? Kindly suggest. Thanks.
7

You have to return a result to the previous page which will represent the action shown on the page.

In the 1st page When you are navigating to the page change a few things.

bool result=await Navigator.of(context).push(/*Wherever you want*/); 

Then in the second page when you are returning to the previous page send some result to the 1st page.

Navigator.of(context).pop(true); 

if the work is not success you can return false.

You can return any type of object as result

Then In the 1st page you can check for the result and show the snackBar accordingly

bool result=await Navigator.of(context).push(/*Wherever you want*/); if(result!=null && result==true){ //Show SnackBar }else{ //Some other action if your work is not done } 

Comments

3

Since showing SackBar require an active Scaffold, you will need to pass the message to the new route page something like getSavedThingRoute(message: 'You saved the thing!') and the new page is responsible for displaying the message.

Typically I happen to use Navigation.pop({'message': 'You saved the thing!', 'error': false}) to pass the message.

2 Comments

The context changes and my app crashes even though I followed the full documentation steps!
3

In your 2nd Page's class, override the initState method

@override void initState() { super.initState(); // Shows the SnackBar as soon as this page is opened. Future(() { final snackBar = SnackBar(content: Text('Hello World')); ScaffoldMessenger.of(context).showSnackBar(snackBar); }); } 

2 Comments

it's second part of solution, could you please suggest me how did you set snackbar message on 1st page? Thanks.
Thanks, I have solved my problem. Just set snackbar message on firstpage and navigate to second page. I can see snackbar message on second page, was set on first page. Thanks again.
1

In case anyone using Flushbar plugin. Put this Inside your build function before return statement.

WidgetsBinding.instance.addPostFrameCallback((timeStamp) { Flushbar( message: "Message from the top", flushbarPosition: FlushbarPosition.TOP, icon: Icon( Icons.info_outline, size: 28.0, color: Color(0xff00d3fe), ), flushbarStyle: FlushbarStyle.FLOATING, duration: Duration(seconds: 5), )..show(_scaffoldKey.currentState.context); });} 

of course don't forget the scaffold key

final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); 

Comments

1

For anyone having this issue in 2023, after scaffoldKey.currentState.showSnackBar() (where scaffoldKey = GlobalKey<ScaffoldState>()) got deprecated, and Flutter introduced

ScaffoldMessenger.of(context).showSnackBar(Snackbar(content: Text(''))) 

which supports displaying the Snackbar on every screen even after navigation, make sure the screen you're navigating to has a Scaffold. My problem was that the screen I was returning to didn't had a scaffold. It was just returning the Material() widget as it was the Splash screen of the application.

You can also use a global key if necessary, like so:

final _scaffoldKey = GlobalKey<ScaffoldMessengerState>(); 

then using it as mentioned in previous comments

_scaffoldKey.currentState.showSnackbar(); 

as shown in the official documentation or this official video

Comments

0

In my case the reason for the snackbar not being shown was the floating action button , I had a logic to put the fab or not and when there was no fab the snack bar did not show , I did not find a proper solution for this but putting a fab like this solved my problem . however putting Container() , null will cause problems.

 Visibility( visible: false, child: FloatingActionButton( onPressed: () {}, ), ); 

Comments

0

var msg = ScaffoldMessenger.of(context) .showSnackBar( SnackBar( content: Text('Processing Data'), ), ); msg.closed.then( (value) => Navigator.pushNamed( context, '2'), );

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.