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