'How can I show a snackbar after navigator.pop(context) in Flutter?

We need close one screen and open a second screen. And show snackbar on the second screen from first screen.

I tried to use Navigator.push, but this screen is already open and we have this error

Bad state: Stream has already been listened to.



Solution 1:[1]

Instead of Snackbar i would suggest you to use Flushbar plugin for flutter it is easy to use and it'll take care of everything and u can customize it to a great extent . Snackbar needs a scaffold ancestor to work but Flushbar doesn't and it takes care of all the extra stuff itself and provides with ton of cool features.

Flushbar Plugin here

Solution 2:[2]

I'm not sure I understand 100% the use case you have but by returning results from screens and passing arguments to new routes, you can work around basically any scenario.

Let's take an example. A is the original screen, then you push screen B. Now you see B, perform some action there, pop it, you get back to screen A and you want to display a snackbar.

When you pop, you can return a result and handle that result from the "parent" screen as described in the "Return data from a screen" cookbook.

When you receive a result, you can either show a snackbar notification, or alternatively (in case there is a third screen), you can pass that result to another screen as argument.

Solution 3:[3]

showSubmitRequestSnackBar(BuildContext context) async {

  Flushbar(
    flushbarPosition: FlushbarPosition.BOTTOM,
    message: "Request Successfully Saved",
    icon: Icon(
      Icons.info_outline,
      size: 28.0,
      color: Colors.red,
    ),
    backgroundColor: Colors.red,
    duration: Duration(seconds: 5),
    leftBarIndicatorColor: Colors.red,

  )
    ..show(context).then((r)=> Navigator.push(
        context, MaterialPageRoute(builder: (context) => ListPage(""))));
}

Solution 4:[4]

Screen A

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => BScreen(
      callbackFunction: (String resMessage){
        print(resMessage);
      },
    ),
  ),
);

Screen B

class BScreen extends StatefulWidget {
  final Function callbackFunction;

  BScreen({required this.callbackFunction});

  @override
  _BScreenState createState() => _BScreenState();
}


class _BScreenState extends State<BScreen> {
  // 
  _performTask(){
    // add your task here
    // ..........
    String msg = 'Task has been added';
    widget.callbackFunction(msg);
    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            _performTask();
          },
          child: Text('Click Here'),
        ),
      ),
    );
  }
}

This solution worked for me. Happy to help others :) Thanks for asking this question.

Solution 5:[5]

Please read this documentation by Flutter that answers your question with example.

What you have to do is, when you are going to Navigator.pop you can pass a message and based on that message you can show SnackBar in the previous screen where you did Navigator.push

So when you pop do something like this:

Navigator.pop(context, 'Yes');
Navigator.pop(context, 'No');

Here, you are passing a message and based on this message you can show the Snackbar in the previous screen where you pushed like this:

final result = await Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => const SelectionScreen()),
  );

  // After the Selection Screen returns a result, hide any previous snackbars
  // and show the new result.
  ScaffoldMessenger.of(context)
    ..removeCurrentSnackBar()
    ..showSnackBar(SnackBar(content: Text('$result')));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Vince Varga
Solution 3
Solution 4 Kamlesh
Solution 5 MD. Saffan Alvy