Home > Blockchain >  Show Snackbar on top route after closing a page
Show Snackbar on top route after closing a page

Time:06-25

In my app, I have some areas where I can open a new page on top of the current, that allow to edit data. Once editing is done, I want to close the page (i.e. via Navigator.pop(context);), and also show a Snackbar after closing (i.e. via ScaffoldMessenger.of(context).showSnackBar('X has been saved')). I am using a ScaffoldMessenger for that.

However, if after closing the edit-page only the top-route remains, the Snackbar will not be shown. If I open any other page fast enough, it will be shown there for the remaining time though. So it was triggered, it is just not shown on the top-route. Also, if I open the edit-page not from the top-route, but from any other page that was already opened on top, the Snackbar will show normally after closing the edit-page.

If I open a Snackbar directly on the top-route, it also works fine. So instead of opening the Snackbar from the edit-page, I could technically return the message and then trigger the Snackbar. But I would prefer not to to pass data around and call functionality at several places, but just call the method at one place (where it belongs).

I can reproduce this behaviour on a newly created App, just need to replace the _MyHomePageState with the following code. What am I doing wrong here?

class _MyHomePageState extends State<MyHomePage> {
  final GlobalKey<ScaffoldMessengerState> _globalScaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
  @override
  Widget build(BuildContext context) {
    return ScaffoldMessenger(
      key: _globalScaffoldMessengerKey,
      child: Scaffold(
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              Navigator.push<bool>(context, MaterialPageRoute(builder: (context) => const SubPage()));
            },
            child: const Text("Open Subpage"),
          ),
        ),
      ),
    );
  }
}

class SubPage extends StatelessWidget {
  const SubPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
            ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Hello Snackbar')));
          },
          child: const Text("Close Subpage"),
        ),
      ),
    );
  }
}

CodePudding user response:

Remove the scaffold Messenger widget from the first page

import 'dart:math';

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
                context, MaterialPageRoute(builder: (context) => const SubPage()));
          },
          child: const Text("Open Subpage"),
        ),
      ),
    );
  }
}

class SubPage extends StatelessWidget {
   const SubPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
            ScaffoldMessenger.of(context)
                .showSnackBar(SnackBar(content: Text('Hello Snackbar')));
          },
          child: const Text("Close Subpage"),
        ),
      ),
    );
  }
}

I checked this code and it shows snackbar in the page that exists after popping the subpage

  • Related