5

So I have a requirement, where I need to show the Snackbar just when the application starts, but when I try to do it, it gives me context error. How can I know that my Widget tree has been built and use the context to display the Snackbar.

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: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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> {
  @override
  Widget build(BuildContext context) {
    Scaffold.of(context).showSnackBar(SnackBar(content: Text('Welcome User')));
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[],
        ),
      ),
    );
  }
}
Gurleen Sethi
  • 3,162
  • 6
  • 26
  • 48

2 Answers2

8

Create a GlobalKey of type ScaffoldState to make sure you target the right Scaffold to show a SnackBar on.

Set your target Scaffold's key to the key you have created.

In your initState() function use WidgetsBinding class and addPostFrameCallback to execute your code when the layout is built. Show your SnackBar in the call back.

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: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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 _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  void initState() {
    super.initState();

    WidgetsBinding.instance.addPostFrameCallback((_) => _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text('Welcome User'))));
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      key: _scaffoldKey,
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[],
        ),
      ),
    );
  }
}
Javid Noutash
  • 2,142
  • 17
  • 19
  • Well, that worked! Could you tell me what this function does and are there similar functions to listen to WidgetTree state. – Gurleen Sethi Jul 22 '18 at 08:57
1

You don't need GlobalKey, Builder or any typical stuff like that. Simply use ScaffoldMessenger.of(context).showSnackBar().

Full code:

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();
    final snackBar = SnackBar(content: Text('Hi'));
    Future(() => ScaffoldMessenger.of(context).showSnackBar(snackBar));
  }

  @override
  Widget build(BuildContext context) => Scaffold();
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
  • It would also be worth mentioning that this is a breaking change API, that isn't available on the Stable channel yet. It's most likely on the Master channel. – Adeolaex Dec 03 '20 at 15:43
  • How can you show this every-time the app come to the foreground? Currently, it will only show when the page rebuild.. The selected page is not rebuild if the app comes to the foreground. – user2570135 May 08 '21 at 16:18