Display SnackBar in Flutter

匿名 (未验证) 提交于 2019-12-03 01:18:02

问题:

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

回答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.



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



回答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.



回答4:

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(new SnackBar(new Text(value))); 


回答5:

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


回答6:

I dit it, work for me :)

@override Widget build(BuildContext context) {   return new Scaffold(     appBar: new AppBar(       title: new Text('Demo')     ),     body: new Builder(       // Create an inner BuildContext so that the onPressed methods       // can refer to the Scaffold with Scaffold.of().       builder: (BuildContext context) {         return new Center(           child: new RaisedButton(             child: new Text('SHOW A SNACKBAR'),             onPressed: () {               Scaffold.of(context).showSnackBar(new SnackBar(                 content: new Text('Hello!'),               ));             },           ),         );       },     ),   ); } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!