85

I want to display a simple SnackBar inside Flutter's Stateful widget. My application creates new instance of MaterialApp with a stateful widget called MyHomePage.

I try to show the SnackBar in showSnackBar() method. But it fails with The method showSnackBar was called on null.

What's wrong with this code?

class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter', theme: new ThemeData( primarySwatch: Colors.blue, ), home: new MyHomePage(), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key}) : super(key: key); @override _MyHomePageState createState() => new _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); @override void initState() { super.initState(); showInSnackBar("Some text"); } @override Widget build(BuildContext context) { return new Padding( key: _scaffoldKey, padding: const EdgeInsets.all(16.0), child: new Text("Simple Text") ); } void showInSnackBar(String value) { _scaffoldKey.currentState.showSnackBar(new SnackBar( content: new Text(value) )); } } 

SOLUTION:

class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter', theme: new ThemeData( primarySwatch: Colors.blue, ), home: new Scaffold(body: new MyHomePage()), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key}) : super(key: key); @override _MyHomePageState createState() => new _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override void initState() { super.initState(); } @override Widget build(BuildContext context) { showInSnackBar("Some text"); return new Padding( padding: const EdgeInsets.all(16.0), child: new Scaffold( body: new Text("Simple Text") ) ); } void showInSnackBar(String value) { Scaffold.of(context).showSnackBar(new SnackBar( content: new Text(value) )); } } 
5
  • 1
    i would rather suggest all the flutter users to use flushbar plugin . You can look at this answer why you should use flushbar plugin instead of directly using snackbar. go look at this answer. stackoverflow.com/a/51261864/7940500 Commented Jul 20, 2018 at 11:21
  • Just use an async function to call your snackbar, if you put your function in build instead of initstate you will get the snackbar popping up each time there's a setstate Commented Aug 6, 2018 at 2:10
  • Here is a tutorial video on how to make the SnackBar widget available to any page, if you are quite confused: youtu.be/u9KoFtu0HEY Commented Jul 5, 2020 at 12:20
  • 2
    Scaffold.of() is deprecated for showing SnackBars, use ScaffoldMessenger instead. Commented Jan 22, 2021 at 15:00
  • u may try this stackoverflow.com/a/69344954/4153682 Commented Feb 18, 2022 at 9:05

20 Answers 20

77

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 :)

Sign up to request clarification or add additional context in comments.

3 Comments

The Flutter documentation describes this as "A less elegant but more expedient solution..". Please tread carefully :) Source: github.com/flutter/flutter/blob/master/packages/flutter/lib/src/…
That's the perfect use case for ScaffoldKey!
showSnackBar method not founded on currentState
54

There's three problems. The first is that you don't have a Scaffold anywhere, and the Scaffold widget is the one that knows how to show snack bars. The second is that you have a key for getting a hold of the scaffold, but you've put it on a Padding instead (and Paddings don't have any knowledge of snack bars). The third is that you've used the key before the widget that it's associated with has had a chance to be initialised, since initState is called before build.

The simplest solution is to change the home line in your MyApp widget to:

home: new Scaffold(body: new MyHomePage()),

...and then remove all mention of _scaffoldKey and instead use Scaffold.of(context) where you currently have _scaffoldKey.currentState.

4 Comments

wrapping my StatefulWidget with a new Scaffold and using Scaffold.of(context) instead of the _scaffoldKey reference helps. Thanks!
Having nested Scaffolds is strongly discouraged, so be careful here!
@Westy92, It's interesting comments, could you please show us why? I have seen someone encouraged to use scaffold wrapping every widget, but I don't believe, tho.
45

ScaffoldState is now deprecated. Use ScaffoldMessengerState.

There are generally two ways of showing the SnackBar using ScaffoldMessenger.


  1. Direct way:

    @override Widget build(BuildContext context) { return Scaffold( body: ElevatedButton( onPressed: () { var snackBar = SnackBar(content: Text('Hello World')); ScaffoldMessenger.of(context).showSnackBar(snackBar); }, child: Text('Show SnackBar'), ), ); } 

  1. Using GlobalKey.

    final _globalKey = GlobalKey<ScaffoldMessengerState>(); @override Widget build(BuildContext context) { return ScaffoldMessenger( key: _globalKey, child: Scaffold( body: Center( child: ElevatedButton( onPressed: () { var snackBar = SnackBar(content: Text('Hello World')); _globalKey.currentState.showSnackBar(snackBar); }, child: Text('Show SnackBar'), ), ), ), ); } 

1 Comment

don't know why Direct way is not working for me!! in Global way. did not also work in this way rather i have found a better solution somewhere else SnackBar snackBar = SnackBar(content: Text('Please fill all fields'),backgroundColor:Colors.red ,); ScaffoldMessenger.of(_scaffoldKey.currentContext!).showSnackBar(snackBar);
33

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.

2 Comments

How this one is better than approach with GlobalKey provided by @Jack the Ripper?
Because GlobalKey is expensive. See this answer there: stackoverflow.com/questions/51304568/…
14

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!') ) ); 

Comments

11
Scaffold.of(context).showSnackBar( SnackBar(content: Text("Thanks for using snackbar", textAlign: TextAlign.center, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),), duration: Duration(seconds: 2), backgroundColor: Colors.red,) ); 

Comments

10

To initialise a Snackbar on initState() you can execute a function after the layout is built.

void initState() { super.initState(); WidgetsBinding.instance .addPostFrameCallback((_) => _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Your message here..")));} 

Comments

7

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))); 

1 Comment

simply moving the method showInSnackBar() to build() does NOT help. On one hand you're right - initState() is called before the build() method, but even after initState() methods: Scaffold.of(context) as well as field _scaffoldKey.currentState are null.
6

Scaffold.Of(context) is deprecated for showing snackbar.

use the new way:

final snackBar = SnackBar(content: Text('Yay! A SnackBar!')); ScaffoldMessenger.of(context).showSnackBar(snackBar); 

snackbars

Comments

4

In case someone is looking to initialise a Snackbar on initState() (in other words when the page loads here is my solution). Also, I assume you already have the _scaffoldKey in place.

void initState() { super.initState(); Future.delayed(Duration(seconds: 1)).then( (_) => _displaySnackbar ); } // Display Snackbar void get _displaySnackbar { _scaffoldKey.currentState.showSnackBar(SnackBar( duration: Duration(minutes: 1), content: Text('Your snackbar message') )); } 

Comments

4

You can do this in three simple steps.

  1. Make sure you have a key for scaffold. You can create that by writing the below code:

    final _scaffoldKey = GlobalKey<ScaffoldState>(); 

2.Now you have to mention this key inside your Scaffold, by writing the below line inside scaffold:

key:_scaffoldKey, 
  1. Now you can show snackbar by writing:

    final snackBar=SnackBar( content: Text('Your password has been changed successfully'), ); _scaffoldKey.currentState.showSnackBar(snackBar); 

Comments

4

ScaffoldState is now deprecated. Use ScaffoldMessengerState.

All the above solutions are amazing but as it's deprecated now you should use it this way.

 var snackBar = SnackBar(content: Text('Hello World')); ScaffoldMessenger.of(_scaffoldKey.currentContext) .showSnackBar(snackBar ); 

3 Comments

Hi, I've already written this in my answer. There's no benefit in adding the same thing twice.
If I saw your answer in the time I wrote this, I wouldn't waste my time writing a duplicate answer. have a nice day
I just remove the Builder from my answer in the edit. Rest of the things are exactly the same, isn't it?
4

We can use like this

**

ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text("Enter your phone number"), ), ); 

**

Comments

2

Display SnackBar in Flutter

 ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text('Please Enter Valid Data'), backgroundColor: Colors.red, )); 

Example:

 if(value.isNotEmpty && value != null){ ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text('Validated Successfully'), backgroundColor: Colors.green, )); }else{ ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text('Please Enter Valid Data'), backgroundColor: Colors.red, )); } 

Comments

1

The best way is to create a PageWrapper that you can wrap all of your pages to get the context of the Scaffold widget and avoid experiencing these errors again.

Here is a sample of the page wrapper:

import 'package:flutter/material.dart'; class PageWrapper extends StatelessWidget { Widget page; WPage(this.page); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: page ); } } 

Then you can wrap all your pages in the main.dart like these:

import 'package:flutter/material.dart'; void main() => runApp(MaterialApp( initialRoute: '/login', routes: { '/login': (context) => PageWrapper(Login()), '/home': (context) => PageWrapper(Home()) } )); 

Now you can call Scaffold.of(context) anywhere in any page just fine.

Reference: https://noobieprogrammer.blogspot.com/2020/06/how-to-create-error-alert-or-popup.html

or watch the video version (5 min. long): https://youtu.be/u9KoFtu0HEY

Comments

1

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.

Comments

0

In the null safety version--

class _testPageState extends State<testPage> { GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); @override Widget build(BuildContext context) { return MaterialApp( home: SizedBox( child: Scaffold( key: _scaffoldKey, body: Center( child: RaisedButton( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), onPressed: () { final snackBar = SnackBar(content: Text('Your Text')); _scaffoldKey.currentState!.showSnackBar(snackBar); }, child: Text("Show SB"), ) ) ) ) ); } } 

Comments

0

use this package snackbar

customsnackbar: ^0.0.1

showCustomSnackBar("Hello", 10.0 ,5, Colors.white);

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0
ScaffoldMessenger.of(context) .showSnackBar(new SnackBar(content: Text('SnackBar Message'))); 

Comments

0
onPressed: () { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: "pressed".text.make(), )); }, 

1 Comment

Thank you for your interest in contributing to the Stack Overflow community. This question already has quite a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.