I want to display a simple SnackBar inside Flutter\'s stateful widget. My application creates new instance of MaterialApp with a stateful widget ca
There are many ways to open a snackbar, but I need to say that there is a way to open a snackbar without any context, and completely customize it, with color, blur, shape, gradient, icons, and literally do anything with it through this package:
https://pub.dev/packages/get
Instead of passing context, instead of creating a globalKey and attaching it to your Scaffold, you can simply call: Get.snackbar("Hi", "your message");
and ready!
The most interesting thing about this is that you call snackbar from anywhere, you can for example return an error message from your controller whenever there is an API failure.
This is very worth knowing.
you can use this :
final _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
),
}
}
and then
in onPressed()
can add this code
_scaffoldKey.currentState.showSnackBar(
new SnackBar(
content: new Text('Hello this is snackbar!')
)
);
There's a better and cleaner way to display a Snackbar in flutter. I found it the hard way and sharing so that maybe it's helpful for someone else.
No need to change in your main app part
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'MyApp',
theme: new ThemeData(
primarySwatch: Colors.orange),
home: new MainPage());
}
}
Page State code is where things will change.
We know Flutter provides Scaffold.of(context).showSnackBar
. However, the context should be the context of a descendant of a Scaffold, and not the context that includes a Scaffold. In order to avoid error, we need to use a BuildContext for the body of the Scaffold, and store it in a variable, as below.
class MainPageState extends State<MainPage> {
BuildContext scaffoldContext;
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.grey,
appBar: new AppBar(
title: const Text(APP_TITLE),
),
body: new Builder(builder: (BuildContext context) {
scaffoldContext = context;
return new Center(
child: new Text('Hello World', style: new TextStyle(fontSize: 32.0)),
);
}));
}
void createSnackBar(String message) {
final snackBar = new SnackBar(content: new Text(message),
backgroundColor: Colors.red);
// Find the Scaffold in the Widget tree and use it to show a SnackBar!
Scaffold.of(scaffoldContext).showSnackBar(snackBar);
}
}
Now, you can call this function from anywhere and it will display the Snackbar. For example, I am using it to display Internet Connectivity messages.
If you are inside a widget that does not has directly the return Scaffold(...)
widget, you can do this:
Scaffold.of(context).showSnackBar(SnackBar(content: Text("Hello from snackbar")));
There is no need to create an extra Scaffold widget because the showSnackBar() method requires one, you can reuse.
In my case i had code like this (in class state)
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
void showInSnackBar(String value) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(content: new Text(value)));
}
but i didn't setup the key for scaffold. so when i add key: _scaffoldKey
@override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
body: new SafeArea(
snackbar start to work :)
initState
been called before build
I guess _scaffoldKey.currentState
has not been initialized when it is call.
I don't know if you can get a ScaffoldState
from initState
. If you change your code you can show the snackbar from build
method with:
Scaffold.of(context).showSnackBar(SnackBar(Text(value)));