Display SnackBar in Flutter

114,875

Solution 1

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 2

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 3

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

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

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!')
       )
);
Share:
114,875
kosiara - Bartosz Kosarzycki
Author by

kosiara - Bartosz Kosarzycki

I'm a senior Java/Android developer constantly developing his skills more here: https://sites.google.com/site/bkosarzyckiaboutme/

Updated on July 05, 2022

Comments

  • kosiara - Bartosz Kosarzycki
    kosiara - Bartosz Kosarzycki almost 2 years

    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)
        ));
      }
    }
    
  • kosiara - Bartosz Kosarzycki
    kosiara - Bartosz Kosarzycki over 7 years
    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.
  • kosiara - Bartosz Kosarzycki
    kosiara - Bartosz Kosarzycki over 7 years
    wrapping my StatefulWidget with a new Scaffold and using Scaffold.of(context) instead of the _scaffoldKey reference helps. Thanks!
  • Westy92
    Westy92 over 5 years
    Having nested Scaffolds is strongly discouraged, so be careful here!
  • Tokenyet
    Tokenyet almost 5 years
    @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.
  • Westy92
    Westy92 almost 5 years
  • Kirill Karmazin
    Kirill Karmazin over 4 years
    How this one is better than approach with GlobalKey provided by @Jack the Ripper?
  • Rohan Taneja
    Rohan Taneja about 4 years
    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/…
  • live-love
    live-love about 4 years
    Because GlobalKey is expensive. See this answer there: stackoverflow.com/questions/51304568/…
  • Ashwin Balani
    Ashwin Balani over 3 years
    That's the perfect use case for ScaffoldKey!
  • CopsOnRoad
    CopsOnRoad over 3 years
    Hi, I've already written this in my answer. There's no benefit in adding the same thing twice.
  • Ezaldeen sahb
    Ezaldeen sahb over 3 years
    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
  • CopsOnRoad
    CopsOnRoad over 3 years
    I just remove the Builder from my answer in the edit. Rest of the things are exactly the same, isn't it?