How to solve: Scaffold.of() called with a context that does not contain a Scaffold

Question

Asked by Figen G on July 12, 2018 (source).

As you can see, my button is inside the Scaffold's body. But I get this exception:

Scaffold.of() called with a context that does not contain a Scaffold.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SnackBar Playground'),
      ),
      body: Center(
        child: RaisedButton(
          color: Colors.pink,
          textColor: Colors.white,
          onPressed: _displaySnackBar(context),
          child: Text('Display SnackBar'),
        ),
      ),
    );
  }
}

_displaySnackBar(BuildContext context) {
  final snackBar = SnackBar(content: Text('Are you talkin\' to me?'));
  Scaffold.of(context).showSnackBar(snackBar);
}

EDIT:

I found another solution to this problem. If we give the Scaffold a key which is the GlobalKey<ScaffoldState>, we can display the SnackBar as following without the need to wrap our body within the Builder widget. The widget which returns the Scaffold should be a Stateful widget though.

 _scaffoldKey.currentState.showSnackBar(snackbar); 

Answer

Question answered by Rémi R (source).

This exception happens because you are using the context of the widget that instantiated Scaffold. Not the context of a child of Scaffold.

You can solve this by just using a different context :

Scaffold(
    appBar: AppBar(
        title: Text('SnackBar Playground'),
    ),
    body: Builder(
        builder: (context) => 
            Center(
            child: RaisedButton(
            color: Colors.pink,
            textColor: Colors.white,
            onPressed: () => _displaySnackBar(context),
            child: Text('Display SnackBar'),
            ),
        ),
    ),
);

Note that while we're using Builder here, this is not the only way to obtain a different BuildContext.

It is also possible to extract the subtree into a different Widget (usually using extract widget refactor)

FLUTTER SCAFFOLD SNACKBAR
SHARE: