Search code examples
dartflutterscaffold

Why does passing BuildContext say there is no Scaffold in that Context?


import 'package:flutter/material.dart';

main() {
  runApp(MaterialApp(
    home: HomeScreen(),
  ));
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Rite.ly'),
      ),
      body: new Container(
          decoration: new BoxDecoration(
              image: new DecorationImage(
            image: new AssetImage('assets/login_background.png'),
            fit: BoxFit.fill,
          )),
          child: new ListView(
            children: [
              new Padding(
                padding:
                    const EdgeInsets.only(top: 16.0, bottom: 8.0, left: 16.0),
                child: new Text('Link : ',
                    style: new TextStyle(color: Colors.white)),
              ),
              _takeUrl(context),
            ],
          )),
    );
  }
}

Widget _takeUrl(BuildContext context) {
  return new Container(
      margin: new EdgeInsets.symmetric(horizontal: 20.0),
      decoration: new BoxDecoration(
          color: Colors.white, borderRadius: new BorderRadius.circular(12.0)),
      child: new Row(
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          new Expanded(
            child: new Column(
              children: [
                new TextField(
                  decoration: new InputDecoration(
                      contentPadding: const EdgeInsets.all(16.0),
                      hintText: 'Link to be Shortened'),
                ),
              ],
            ),
          ),
          new IconButton(
            icon: new Icon(
              Icons.content_paste,
              color: Color.fromARGB(255, 191, 53, 146),
            ),
            onPressed: () {
              Scaffold.of(context).showSnackBar(new SnackBar(
                    content: new Text('Hello!'),
                  ));
            },
          )
        ],
      ));
}

In the code above, passing the context to a fragment separated from the build method, gives error when Scaffold.of is called as:

I/flutter (20313): Another exception was thrown: Scaffold.of() called with a context that does not contain a Scaffold.

However, this gets solved when we use a Builder widget and pass the _takeURL as builder to the Builder. The Snack Bar works perfectly fine after that.

What might be responsible? What do I need to read to understand why?

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Rite.ly'),
      ),
      body: new Container(
          decoration: new BoxDecoration(
              image: new DecorationImage(
            image: new AssetImage('assets/login_background.png'),
            fit: BoxFit.fill,
          )),
          child: new ListView(
            children: [
              new Padding(
                padding:
                    const EdgeInsets.only(top: 16.0, bottom: 8.0, left: 16.0),
                child: new Text('Link : ',
                    style: new TextStyle(color: Colors.white)),
              ),
              Builder(builder: _takeUrl,),
            ],
          )),
    );
  }
}

Solution

  • The context passed on is not the one needed by Scaffold.of(context). You need to wrap it in a Builder as Flutter BuildContext specifies:

    Widget _takeUrl(BuildContext context) {
    return Builder(builder: (BuildContext context) {
        return new Container(
            margin: new EdgeInsets.symmetric(horizontal: 20.0),
            decoration: new BoxDecoration(
                color: Colors.white, borderRadius: new BorderRadius.circular(12.0)),
            child: new Row(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
                new Expanded(
                child: new Column(
                    children: [
                    new TextField(
                        decoration: new InputDecoration(
                            contentPadding: const EdgeInsets.all(16.0),
                            hintText: 'Link to be Shortened'),
                    ),
                    ],
                ),
                ),
                new IconButton(
                icon: new Icon(
                    Icons.content_paste,
                    color: Color.fromARGB(255, 191, 53, 146),
                ),
                onPressed: () {
                    Scaffold.of(context).showSnackBar(new SnackBar(
                        content: new Text('Hello!'),
                        ));
                },
                )
            ],
            ));
    });
    }