When I was using the old api for showing the snackbar, the snackbar used to disappear when the user goes back to the previous page.

With the new ScaffoldMessenger.of(context).showSnackBar(), the snackbar stays visible.

Also, when I add a snackbar action for removing the snackbar, pressing on the hide action, does not hide the snackbar after going back to the previous page.

How can I remove the snackbar after the user leaves the current page?

void _successSnackbar(BuildContext context, String message) {
  ScaffoldMessenger.of(context).hideCurrentSnackBar();

  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(
      content: Row(
        children: [
          Icon(FontAwesomeIcons.checkCircle, color: Colors.green[400], size: 35),
          const SizedBox(width: 15),
          Flexible(child: Text(message, style: TextStyle(color: Colors.green[400], fontSize: 14.5))),
        ],
      ),
      action: SnackBarAction(
        label: 'Hide',
        onPressed: () {
          ScaffoldMessenger.of(context).hideCurrentSnackBar();
        },
      ),
      duration: Duration(seconds: 2),
    ),
  );


Solution 1: moulte

Instead of passing the context and look for the ScaffoldMessenger pass directly the scaffoldMessenger:

void _successSnackbar(ScaffoldMessengerState scaffoldMessengerState , String message) {
  scaffoldMessengerState.hideCurrentSnackBar();

  scaffoldMessengerState.showSnackBar(
    SnackBar(
      content: Row(
        children: [
          Icon(FontAwesomeIcons.checkCircle, color: Colors.green[400], size: 35),
          const SizedBox(width: 15),
          Flexible(child: Text(message, style: TextStyle(color: Colors.green[400], fontSize: 14.5))),
        ],
      ),
      action: SnackBarAction(
        label: 'Hide',
        onPressed: () {
          scaffoldMessengerState.hideCurrentSnackBar();
        },
      ),
      duration: Duration(seconds: 2),
    ),
  );

To close the snackBar automatically when the page is poped you will have to put a scaffoldMessengerState.hideCurrentSnackBar(); on a will pop callback or in a naavigator observer


Solution 2: chunhunghan

You can copy paste run full code below
Reason
from official document https://flutter.dev/docs/release/breaking-changes/scaffold-messenger
The ScaffoldMessenger creates a scope in which all descendant Scaffolds register to receive SnackBars, which is how they persist across these transitions
so In your case, root ScaffoldMessenger provided by the MaterialApp let all descendant Scaffolds receive SnackBars

Solution
unless a new ScaffoldMessenger scope is created further down the tree. By instantiating your own ScaffoldMessenger, you can control which Scaffolds receive SnackBars
To auto hide SnackBar when pop from second page, you can in second page wrap Scaffold with ScaffoldMessenger and in my example also need Builder

code snippet in Page2

Widget build(BuildContext context) {
    return ScaffoldMessenger(
      child: Scaffold(
         ...
            child: Column(
              children: [
                Text("Second route"),
                Builder(builder: (BuildContext context) {
                  return ElevatedButton(
                      onPressed: () {
                        _successSnackbar(context, "messge of page 2");
                      },
                      child: Text('show message'));
                }),

working demo

enter image description here

full code

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Page 1',
            ),
            ElevatedButton(
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => Page2()),
                  );
                },
                child: Text('Go to page 2'))
          ],
        ),
      ),
    );
  }
}

class Page2 extends StatefulWidget {
  @override
  _Page2State createState() => _Page2State();
}

class _Page2State extends State<Page2> {
  void _successSnackbar(BuildContext context, String message) {
    ScaffoldMessenger.of(context).hideCurrentSnackBar();

    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Row(
          children: [
            Icon(Icons.check, color: Colors.green[400], size: 35),
            const SizedBox(width: 15),
            Flexible(
                child: Text(message,
                    style:
                        TextStyle(color: Colors.green[400], fontSize: 14.5))),
          ],
        ),
        action: SnackBarAction(
          label: 'Hide',
          onPressed: () {
            ScaffoldMessenger.of(context).hideCurrentSnackBar();
          },
        ),
        duration: Duration(seconds: 20),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return ScaffoldMessenger(
      child: Scaffold(
          appBar: AppBar(
            title: Text("page 2"),
          ),
          body: Center(
            child: Column(
              children: [
                Text("Second route"),
                Builder(builder: (BuildContext context) {
                  return ElevatedButton(
                      onPressed: () {
                        _successSnackbar(context, "messge of page 2");
                      },
                      child: Text('show message'));
                }),
                ElevatedButton(
                    onPressed: () {
                      Navigator.pop(
                        context,
                      );
                    },
                    child: Text('Pop'))
              ],
            ),
          )),
    );
  }
}


Solution 3: flomaster

The reason is that we pass the wrong context to ScaffoldMessenger.of() method. We need context of a child of Scaffold.

You can wrap your widget in Builder to get the right context.

In my case it was not possible, so another solution is to use a GlobalKey. In your widget State class add this line: final _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();, use _scaffoldMessengerKey.currentState.showSnackBar() to show snackbar, and wrap your Scaffold with ScaffoldMessenger:

ScaffoldMessenger(
  key: _scaffoldMessengerKey,
  child: Scaffold(...)
)