0

I have 2 screens in my Flutter project:

  1. List of records screen
  2. Add record screen

When a record is submitted and added on "Add record screen" then screen is redirected to "List of records screen" and shows added records on this screen which is working.

My query is that I want to show success message which should set on "Add record screen" and should be shown on "List of records screens" after transition. I am adding snackbar code on "Add record screen" as:

ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('Record has been added successfully.'),
        duration: Duration(milliseconds: 5000),
      ),
    );

It returns error after redirecting to "List of records screens". I think "List of records screens" does not have "context" of snackbar which was set on "Add record screen" that's why I am getting error.

Is there any one, who can help me to understand what is the actual error and how can I show snackbar message on "List of records screens", was set on "Add record screen"?

Any help will be highly appreciated. Thank you.

Kamlesh
  • 5,233
  • 39
  • 50

1 Answers1

1

To show the snackbar on the following page, you could pass the snackbar function to the page you are navigating to and then call it in that page's initState, using the method mentioned in this answer: https://stackoverflow.com/a/50682918/16045128

WidgetsBinding.instance?.addPostFrameCallback((_) { widget.feedback?.call(); });

Feedback Snackbar Demo:

enter image description here

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: const Text('Home Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const <Widget>[
            Icon(Icons.home),
            SizedBox(height: 15),
            Text(
              'Home Page',
            ),
          ],
        ),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          Tooltip(
            message: "Show Snackbar",
            child: ElevatedButton(
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => SecondPage(
                      feedback: () {
                        ScaffoldMessenger.of(context).showSnackBar(
                          const SnackBar(
                            content: Text('You have reached the second page.'),
                            duration: Duration(seconds: 3),
                          ),
                        );
                      },
                    ),
                  ),
                );
              },
              child: const Icon(Icons.check),
            ),
          ),
          const SizedBox(width: 15),
          Tooltip(
            message: "Don't Show Snackbar",
            child: ElevatedButton(
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => const SecondPage(),
                  ),
                );
              },
              child: const Icon(Icons.close),
            ),
          ),
        ],
      ),
    );
  }
}

class SecondPage extends StatefulWidget {
  const SecondPage({Key? key, this.feedback}) : super(key: key);

  final Function? feedback;

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

class _SecondPageState extends State<SecondPage> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance?.addPostFrameCallback(
      (_) {
        widget.feedback?.call();
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: const Text('Second Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const <Widget>[
            Icon(Icons.two_k),
            SizedBox(height: 15),
            Text(
              'Second Page',
            ),
          ],
        ),
      ),
    );
  }
}
Arun
  • 326
  • 1
  • 5
  • Thanks Arun for your suggestion, If I use your solution then I will have to take 'feedback' parameter on all the screens of entire project which is very lengthy process. BTW will we get context in initState function before rendering 'build' method of screen? Thanks again. – Kamlesh May 27 '21 at 17:42
  • 1
    You will have access to the context of that widget in initState. So, you could implement the snackbar there. But you still will have to use the addPostFrameCallback. Trying to render the snackbar before building the widget will cause an exception. Also, implementing the snackbar here without any conditional will cause it to show up every time the page is built for the first time (every time it calls initState). – Arun May 27 '21 at 17:56
  • Thanks, I have updated code on next screen where we will show the snackbar message: if (widget.getSnackbarMessage != null) { WidgetsBinding.instance?.addPostFrameCallback((_) { widget.getSnackbarMessage?.call(); }); } – Kamlesh May 27 '21 at 18:21
  • I have more than 100 screens in my project. Should I need to set `WidgetsBinding.instance?.addPostFrameCallback( (_) { widget.feedback?.call(); }, );` on all the screens? Or do we have any centralized solution of this problem? Kindly share Thanks. – Kamlesh Jul 25 '21 at 13:15