简体   繁体   中英

How to show SnackBar in Flutter

I want to show a SnackBar Widget when the bottom tab is clicked. I am trying to show it as:

Scaffold.of(context).showSnackBar(new SnackBar(
                content: new Text("Live Clicked"),
              ));

However the app throws the following exception:

I/flutter ( 4965): The following assertion was thrown while handling a gesture:
I/flutter ( 4965): Scaffold.of() called with a context that does not contain a Scaffold.
I/flutter ( 4965): No Scaffold ancestor could be found starting from the context that was passed to Scaffold.of(). This
I/flutter ( 4965): usually happens when the context provided is from the same StatefulWidget as that whose build
I/flutter ( 4965): function actually creates the Scaffold widget being sought.
I/flutter ( 4965): There are several ways to avoid this problem. The simplest is to use a Builder to get a context that
I/flutter ( 4965): is "under" the Scaffold. For an example of this, please see the documentation for Scaffold.of():
I/flutter ( 4965):   https://docs.flutter.io/flutter/material/Scaffold/of.html
I/flutter ( 4965): A more efficient solution is to split your build function into several widgets. This introduces a
I/flutter ( 4965): new context from which you can obtain the Scaffold. In this solution, you would have an outer widget
I/flutter ( 4965): that creates the Scaffold populated by instances of your new inner widgets, and then in these inner
I/flutter ( 4965): widgets you would use Scaffold.of().
I/flutter ( 4965): A less elegant but more expedient solution is assign a GlobalKey to the Scaffold, then use the
I/flutter ( 4965): key.currentState property to obtain the ScaffoldState rather than using the Scaffold.of() function.
I/flutter ( 4965): The context used was:
I/flutter ( 4965):   MyHomePage(state: _MyHomePageState(603645610))

Although the exception is self-explanatory. I don't understand why it is occurring since MyHomePage widget has Scaffold in it.

Complete code:

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'App Name',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'App Name'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var bottomBarLabels = [
    new DestinationLabel(
        icon: new Icon(Icons.live_tv), title: new Text("Live")),
    new DestinationLabel(
        icon: new Icon(Icons.date_range), title: new Text("Matches")),
  ];

  @override
  Widget build(BuildContext context) {
    void _handleBottomNavigationBarTap(int newValue) {
      switch (newValue) {
        case 0:
          print("Live Clicked");
          Scaffold.of(context).showSnackBar(new SnackBar(
                content: new Text("Live Clicked"),
              ));
          break;
        case 1:
          print("Matches Clicked");
          break;
      }
    }

    return new Scaffold(
      key: new Key("homepage"),
      appBar: new AppBar(
        title: new Text(config.title),
      ),
      bottomNavigationBar: new BottomNavigationBar(
          labels: bottomBarLabels, onTap: _handleBottomNavigationBarTap),
    );
  }
}

You do have a scaffold, but not above the context of MyHomePage. Your Scaffold is a child of MyHomePage, while doing Scaffold.of(context) is trying to access the closest parent Scaffold. And since you have none, it crash.

You should probably wrap your BottomNavigationBar into a new class. And use that widget's context to do Scaffold.of(context) .

Change your _handleBottomNavigationBarTap method to take a BuildContext argument.

void _handleBottomNavigationBarTap(int newValue, BuildContext context) {
  ...
}

Then change your bottomNavigationBar argument as follows:

bottomNavigationBar: new Builder(
  builder: (BuildContext context) {
    return new BottomNavigationBar(
      labels: bottomBarLabels,
      onTap: (index) => _handleBottomNavigationBarTap(index, context),
    );
  }
),

This ensures that you call to Scaffold.of(context) will be able to find a ScaffoldState that is an ancestor of the context .

Unfortunately I am not able to upgrade my Flutter version at the moment, However, from what I understand, you are trying to show a SnackBar only when Live Icon is pressed.

So you may want to make the Live Icon into an IconButton instead and use its onPressed property on its own instead of using the onTap property of the BottomNavigationBar , then wrap the IconButton within a Builder , something similar to the following:

new BottomNavigationBar(
          labels: [
            new DestinationLabel(title: new Text("Live"),
              icon: new Builder(builder: (BuildContext context) {
                return new IconButton(icon: new Icon(Icons.live_tv),
                    onPressed: () {
                      Scaffold.of(context).showSnackBar(
                          new SnackBar(content: new Text("Live Clicked")));
                    });
              }),
            ),
            new DestinationLabel(icon: new Icon(Icons.date_range),
                title: new Text("Matches"),)


          ],
        )

I am not sure if this is the best practice, our Flutter gurus here always suggest to compose the more complex widgets from multiple classes.

'showSnackBar ' is deprecated and shouldn't be used. Use ScaffoldMessenger.showSnackBar . This feature was deprecated after v1.23.0-14.0.pre..

Use Like this:-

 ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text('User Successfully Logged In...'),
    ));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM