Alexei
Alexei

Reputation: 15726

Not show snackbar

android studio 3.6

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        theme: new ThemeData(
            primaryColor: new Color(Constants.COLOR_PRIMARY),
            primaryTextTheme: TextTheme(headline6: TextStyle(color: Colors.white))),
        home: new SignInForm());
  }
}


class SignInForm extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    logger.d("createState:");
    return new _SignInFormState();
  }
}

class _SignInFormState extends State {
  final _formKey = GlobalKey<FormState>();
  final _scaffoldKey = GlobalKey<ScaffoldState>();
  String _textVersion = "";
  String _email = null;
  String _password = null;

@override
  Widget build(BuildContext context) {
    logger.d("build:");
    //String _errorMessage = null;
    return Scaffold(
        appBar: new AppBar(
            centerTitle: true,
            title: new Text('Sign in',
                style: TextStyle(fontWeight: FontWeight.bold))),
        body: new Container(
            margin: const EdgeInsets.only(
                left: Constants.DEFAULT_MARGIN,
                right: Constants.DEFAULT_MARGIN),
            child: new Form(
                key: _formKey,
                child: new Column(children: [
                  new TextFormField(
                      decoration: new InputDecoration(hintText: 'Email'),
                      keyboardType: TextInputType.emailAddress,
                      onChanged: (value) {
                        setState(() {
                          _email = value;
                        });
                      }),
                  new TextFormField(
                      decoration: new InputDecoration(hintText: 'Password'),
                      obscureText: true),
                  new Container(
                      margin: const EdgeInsets.only(
                          top: Constants.DEFAULT_MARGIN / 2),
                      height: Constants.MIN_HEIGHT,
                      child: new Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            new Text("Forgot password?",
                                style: TextStyle(
                                    color: new Color(Constants.COLOR_PRIMARY))),
                            new Align(
                                alignment: Alignment.centerRight,
                                child: new RaisedButton(
                                    // Buttons are disabled by default
                                    child: Text('Sign in'.toUpperCase()),
                                    color: new Color(Constants.COLOR_PRIMARY),
                                    textColor: new Color(
                                        Constants.COLOR_PRIMARY_TEXT_COLOR),
                                    onPressed: () {
                                      if (_formKey.currentState.validate()) {
                                        logger.d(
                                            "onPressed: check_email = $_email");
                                        if (_email == null ||
                                            _email.trim().isEmpty) {
                                          logger.d(
                                              "onPressed: show_error_message");
                                          Scaffold.of(context).showSnackBar(
                                              SnackBar(
                                                  content: Text("Аll fields must be filled"),
                                                  backgroundColor: Colors.red));
                                        }
                                      }
                                    }))
                          ])),
                  new Container(
                      margin: const EdgeInsets.all(Constants.DEFAULT_MARGIN),
                      child: new Text('Registration'.toUpperCase(),
                          style: new TextStyle(
                              color: new Color(Constants.COLOR_PRIMARY),
                              fontWeight: FontWeight.bold))),
                  new Container(
                      margin: const EdgeInsets.all(Constants.DEFAULT_MARGIN),
                      child: new Text(_textVersion))
                ]))));
  }

press button and get error in in this line:

Scaffold.of(context).showSnackBar(

logcat:

The context used was: SignInForm
  state: _SignInFormState#fe66a
When the exception was thrown, this was the stack: 
#0      Scaffold.of (package:flutter/src/material/scaffold.dart:1456:5)
#1      _SignInFormState.build.<anonymous closure> (package:flutter_sample/signinform.dart:86:52)
#2      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:779:14)
#3      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:862:36)
#4      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
...
Handler: "onTap"
Recognizer: TapGestureRecognizer#74eb7
  debugOwner: GestureDetector
  state: possible
  won arena
  finalPosition: Offset(268.7, 208.0)
  finalLocalPosition: Offset(52.7, 18.0)
  button: 1
  sent tap down

Upvotes: 0

Views: 65

Answers (1)

Midhun MP
Midhun MP

Reputation: 107231

The issue happens because the current passed context doesn't have any matching ancestor (in this case a matching ancestor scaffold).

Option 1:

The easiest way to fix this issue is, in your MyApp, replace:

home: new SignInForm()

with:

home: Scaffold(body: SignInForm())

Option 2:

You have to specify the key property of your scaffold:

Scaffold(key: _scaffoldKey, body: // Your remaining code);

And display the snackbar using:

_scaffoldKey.currentState.showSnackBar(
     SnackBar(content: Text("Аll fields must be filled"),
              backgroundColor: Colors.red)
 );

Option 3:

You can use a Builder widget to fix the issue:

Scaffold(body: Builder(builder: (context) {
    return Container(child:// Your widget);
    // No other change needed
},);

I personally prefer option 3.

When the Scaffold is actually created in the same build function, the context argument to the build function can't be used to find the Scaffold (since it's "above" the widget being returned in the widget tree).

Reference of method

Upvotes: 1

Related Questions