Display SnackBar in Flutter

DartAndroid SnackbarSnackbarFlutter

Dart Problem Overview


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

Dart Solutions


Solution 1 - Dart

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

Solution 2 - Dart

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.

Solution 3 - Dart

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.

Solution 4 - Dart

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'),
            ),
          ),
        ),
      );
    }
    

Solution 5 - Dart

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

Solution 6 - Dart

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..")));}

Solution 7 - Dart

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

Solution 8 - Dart

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

Solution 9 - Dart

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

Solution 10 - Dart

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,

3. Now you can show snackbar by writing:

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

Solution 11 - Dart

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

Solution 12 - Dart

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

Solution 13 - Dart

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

Solution 14 - Dart

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

Solution 15 - Dart

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.

Solution 16 - Dart

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"),
                    )
                )
            )
        )
    );
  }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionkosiara - Bartosz KosarzyckiView Question on Stackoverflow
Solution 1 - DartJakub S.View Answer on Stackoverflow
Solution 2 - DartIan HicksonView Answer on Stackoverflow
Solution 3 - DartWahib Ul HaqView Answer on Stackoverflow
Solution 4 - DartCopsOnRoadView Answer on Stackoverflow
Solution 5 - DartRizki SyaputraView Answer on Stackoverflow
Solution 6 - DartSyed AhmedView Answer on Stackoverflow
Solution 7 - Dartyubaraj poudelView Answer on Stackoverflow
Solution 8 - DartAlexandre ArdhuinView Answer on Stackoverflow
Solution 9 - DartAlvin KondaView Answer on Stackoverflow
Solution 10 - DartSunpreet SinghView Answer on Stackoverflow
Solution 11 - DartEzaldeen sahbView Answer on Stackoverflow
Solution 12 - DartfaridfedoraView Answer on Stackoverflow
Solution 13 - DartSuresh B BView Answer on Stackoverflow
Solution 14 - DartdoppelgunnerView Answer on Stackoverflow
Solution 15 - DartJuanma MenendezView Answer on Stackoverflow
Solution 16 - DartVishal AgrawalView Answer on Stackoverflow