1

I have same question as Show a snackbar after navigate in Flutter but for https://pub.dev/packages/flushbar

How can I show flushbar after navigation?

(In first route, when we navigate to second route, we have a background task, the task may fail, I want to show a message to end usee by flush bar, UI is in SecondRoute (or may be another route) and In FiratRout after (or before , no matter) navigation, background task runned and after a while may be failed

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Navigation Basics',
    home: FirstRoute(),
  ));
}

class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Open route'),
          onPressed: () async {
            await Navigator.pushReplacement(
              context,
              MaterialPageRoute(builder: (context) => SecondRoute()),
            );
            Flushbar(
              title: "Hey Ninja",
              message:
                  "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
              duration: Duration(seconds: 3),
            )..show(context);
          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: Text(
            "I want to show here Flushbar, Flushbar.show called in FirstRoute"),
      ),
    );
  }
}

WebMaster
  • 3,050
  • 4
  • 25
  • 77

2 Answers2

3

You can show flushbar after navigating by using

SchedulerBinding.instance?.addPostFrameCallback();

So, your onPressed code will be something like this.

await Navigator.pushReplacement(
  context,
  MaterialPageRoute(builder: (context) => SecondRoute()),
);
SchedulerBinding.instance?.addPostFrameCallback((_) {
  Flushbar(
    title: "Hey Ninja",
    message:
    "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
    duration: Duration(seconds: 3),
  )..show(context);
});

Hope it works.

Dharman
  • 30,962
  • 25
  • 85
  • 135
kevinkwee
  • 123
  • 1
  • 6
1
Navigator.push()

is a Future type so awaiting it should be all you need as long as you are returning back to the widget you pushed from.

Example with regular snackbar:

Future routeAndShowSnack() async {
   await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => OtherWidget(param: value))
   );
   _scaffoldKey.currentState.show(SnackBar(content: Text('Heres a snack'));
}

You need to make sure the context you are calling scaffold with is the correct context. If you are calling context above the scaffold then it will fail gracefully and not show a snackbar. Please show Widget build() code if you are unsure about the scaffold context.

NOTE: I just copied this code from a repo I have. You do not need to route with the material page route builder widget.

Example below of what you are trying to achieve.

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

  final String title;

  @override
  _FirstRouteState createState() => _FirstRouteState();
}

class _FirstRouteState extends State<FirstRoute> {
  final  GlobalKey<ScaffoldState> _keyin = GlobalKey();

  void _flush(BuildContext context) async {
    await Navigator.of(context).push(
      MaterialPageRoute(builder: (context) => SecondRoute()),
    );
    Flushbar(
      title: "Hey Ninja",
      message:
          "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
      duration: Duration(seconds: 3),
    )..show(context);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _keyin,
      appBar: AppBar(
        title: Text(widget.title),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _flush(context),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: OutlineButton(
          child: Text('Back'), 
          onPressed: () => Navigator.of(context).pop()
        ),
      ),
    );
  }
}

As I commented below, you cannot achieve this functionality with pushReplacement as that breaks the concept of waiting for a route to return back to the initial route. If you replace a route in the navigator tree then anything you wanted to run has been disposed of.

Nicholas Pesa
  • 2,156
  • 2
  • 24
  • 45
  • What if I don't use `Navigator.push` and use `pushReplacementNamed` ? – WebMaster May 07 '20 at 07:34
  • Where you set _scaffoldKey? – WebMaster May 07 '20 at 07:34
  • pushReplacementNamed might only work if there is a route to back navigate to. Can you please show your widget code so I can see the context being used for scaffold? I can show you how to use the GlobalKey for scaffold also – Nicholas Pesa May 07 '20 at 08:03
  • see https://flutter.dev/docs/cookbook/navigation/navigation-basics , in FirstRoute's onPressed , I want to pushReplacementNamed to SecondRoute then show Flushbar not SnackBar – WebMaster May 07 '20 at 08:08
  • 1
    Ok you cannot use `pushReplacement` because then you cannot navigate back to the FirstRoute. If you are replacing the route in the navigator tree how could it possibly return to the FirstRoute? Example of using Navigator.push() above which I have verified does work on my local machine. – Nicholas Pesa May 07 '20 at 19:52
  • I dont want to navigate back, I want to show flushbar in second route from the first route,in first route we have a background task, it may fail, I want to show snackbar that ot failed, but UI is in second(or may be another) route – WebMaster May 08 '20 at 07:37