How to display SnackBar in Flutter?

3,343

Solution 1

"Scaffold.of(context)" has been deprecated, will return null. Now use "ScaffoldMessenger.of(context)". As per Flutter documentation.

  @override
  Widget build(BuildContext context) {
// here, Scaffold.of(context) returns null
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            ScaffoldMessenger.of(context).showSnackBar(SnackBar(
              content: const Text('snack'),
              duration: const Duration(seconds: 1),
              action: SnackBarAction(
                label: 'ACTION',
                onPressed: () { },
              ),
            ));
          },
          child: const Text('SHOW SNACK'),
        ),
      ),
    );
  }

NOTE: Make sure your main.dart overrided build() function should return "MaterialApp" as a widget, such as:

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
   // Must be MaterialApp widget for ScaffoldMessenger support.
  return MaterialApp(  
      title: 'My App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyDashboard(),
    );
  }
}

Solution 2

You can normally use snack bar in the Bottom Navigation bar in this way. However, if you want to show it in the body, then just copy the code from Builder and paste it in the body of the scaffold.

      Scaffold(bottomNavigationBar: Builder(builder: (context) => Container(child: Row(children: <Widget>[
      Icon(Icons.add_alarm), Icon(Icons.map),    IconButton(icon: Icon(Icons.bookmark),
            onPressed:() {
        Scaffold.of(context).showSnackBar(mySnackBar);
            
              final mySnackBar =  SnackBar(
              shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
              behavior: SnackBarBehavior.floating,
              backgroundColor: Colors.white, duration: Duration(seconds: 1),
              content: Text(
                'Article has been removed from bookmarks',
                
              ),);
        } 
),
    ],
),
),
),
);

Note: In the behaviour property of SnackBar, you can just leave it empty. But the problem with that is "If you have Curved Navigation Bar or you have a floating action button above the bottom navigation bar, then the snackbar will lift these icons (or FAB ) and will affect the UI". That's why SnackBar.floating is more preferred as it is more capatible with the UI. But you can check and see on your own which suits you the best.

Solution 3

So based on the error, it would seem that the context passed in Snackbar.of() is not the correct context. This would make sense based on 1 & 2; and summary copied below:

Each widget has its own BuildContext, which becomes the parent of the widget returned by the StatelessWidget.build or State.build function. (And similarly, the parent of any children for RenderObjectWidgets.)

In particular, this means that within a build method, the build context of the widget of the build method is not the same as the build context of the widgets returned by that build method.

So this means that the build context you are passing in jelszoba(context) function is not the build context you need and is actually the build context of the widget that is instantiating the Scaffold.

So How to Fix: To fix this wrap your Card widget in your SnackbarPage in a Builder widget and pass the context from it, to the jelszoba(context) method.

An example from 1 I post below:

@override
Widget build(BuildContext context) {
// here, Scaffold.of(context) returns null
return Scaffold(
  appBar: AppBar(title: Text('Demo')),
  body: Builder(
    builder: (BuildContext context) {
      return FlatButton(
        child: Text('BUTTON'),
        onPressed: () {
          // here, Scaffold.of(context) returns the locally created Scaffold
          Scaffold.of(context).showSnackBar(SnackBar(
            content: Text('Hello.')
          ));
        }
      );
    }
  )
);
}
Share:
3,343
jdsflk
Author by

jdsflk

High school student, interested in Python, C++, Java and Flutter.

Updated on December 21, 2022

Comments

  • jdsflk
    jdsflk over 1 year

    I want to display a SnackBar in my Flutter app. I have read the docs and copyed it:
    The body of my scaffold:

    Widget build(BuildContext context) {
        return WillPopScope(
          onWillPop: () async => false,
          child: Scaffold(
            appBar: AppBar(
              centerTitle: true,
              title: Text("Osztályok"),
              leading: Padding(
                  padding: const EdgeInsets.only(left: 5.0),
                  child: IconButton(
                      icon: Icon(Icons.exit_to_app, color: Colors.white70),
                      onPressed: () {
                        authService.signOut();
                        authService.loggedIn = false;
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => GoogleSignUp()));
                      })),
              actions: <Widget>[
                Padding(
                    padding: const EdgeInsets.only(right: 5.0),
                    child: Row(
                      children: <Widget>[
                        IconButton(
                            icon: Icon(Icons.add_circle_outline,
                                color: Colors.white70),
                            onPressed: () {
                              createPopup(context);
                            }),
    //                    IconButton(
    //                        icon: Icon(Icons.search, color: Colors.black38),
    //                        onPressed: null),
                      ],
                    )),
              ],
            ),
    

    The SnackBarPage class:

    class SnackBarPage extends StatelessWidget {
    
      void jelszopress(TextEditingController jelszoController, BuildContext context) async{
        var jelszo;
        DocumentReference docRef =   
        Firestore.instance.collection('classrooms').document(globals.getid());
        await docRef.get().then((value) => jelszo= (value.data['Jelszo']) );
        if (jelszo == jelszoController.text.toString()){
          Navigator.push(context,
              MaterialPageRoute(builder: (context) => InClassRoom()));
        }
        else{
          Navigator.pop(context);
    
    
          final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
    
          Scaffold.of(context).showSnackBar(snackBar);
        }
      }
    Future<String> jelszoba(BuildContext context) {
        TextEditingController jelszoController = TextEditingController();
        return showDialog(
            context: context,
            builder: (context) {
              return AlertDialog(
                  title: Text('Add meg a jelszót'),
                  content: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.all(Radius.circular(20)),
                      ),
                      child: TextField(
                          controller: jelszoController,
                          decoration: InputDecoration(hintText: "Jelszó")
                      )
                  ),
                  actions: <Widget>[
                    MaterialButton(
                      elevation: 5.0,
                      child: Text('Mehet'),
                      onPressed: () {
                        jelszopress(jelszoController, context);
                      },
                    )]);
            }
        );
      }
    
      var nevek;
      var IDS;
      SnackBarPage(this.nevek, this.IDS);
      @override
      Widget build(BuildContext context){
        return ListView.builder(
          itemCount: nevek.length,
          itemBuilder: (context, index) {
            return Card(
              child: ListTile(
                onTap: () {
                  globals.setid(IDS[index]);
                  jelszoba(context);
    
                },
                title: Text(nevek[index]),
              ),
            );
          },
        ) ;
    
      }
    }
    

    But my cody doesn't display the SnackBar. I tried the solution of this question: How to properly display a Snackbar in Flutter? but adding a Builder widget didn't help.

    • Mohammad Assad Arshad
      Mohammad Assad Arshad almost 4 years
      Do you get any errors in the console?
    • Danaru
      Danaru almost 4 years
      SnackBar must be into Scaffold Widget. Can we see the parent widget using SnackBarPage()
    • jdsflk
      jdsflk almost 4 years
      @Danaru I have edited the post.
    • jdsflk
      jdsflk almost 4 years
      @MohammadAssadArshad I get this: [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Scaffold.of() called with a context that does not contain a Scaffold.