AndreHaueisen / flushbar

Custom widget for Flutter
Other
1.01k stars 172 forks source link

Navigator.pop #172

Open sm2017 opened 3 years ago

sm2017 commented 3 years ago

I am using flutter bloc in my application, is success response I call Navigator.pop to pop the navigator, and in failure I call Flushbar.show to to toast error message

As you push in navigator I have some problem, When I call Navigator.pop and the previous toast is exists in the page , it popped instead of the current page

I know I can use Navigator.popUntil, But I think it is the problem of flushbar library, Because toast must not be a different route

SardorbekR commented 3 years ago

@sm2017 Have you found a solution?

sm2017 commented 3 years ago

@SardorbekR No @AndreHaueisen Can you please reply, I think you shouldn't use navigation API to show toast

cmdrootaccess commented 3 years ago

@sm2017 you can use toast in a provider , that will fix it

sm2017 commented 3 years ago

@cmdrootaccess Can you show me a sample code for flushbar

cmdrootaccess commented 3 years ago

yes i will make an example in the next few hours and show you

sm2017 commented 3 years ago

@cmdrootaccess Can you help me?

cmdrootaccess commented 3 years ago

sorry was busy. let me paste the code here. give me a moment

cmdrootaccess commented 3 years ago

create provider.dart . paste this

import 'package:flutter/material.dart';
import 'package:testtoast/toast.dart';

class AppProvider extends StatefulWidget {
  final Widget child;

  const AppProvider({Key key, @required this.child}) : super(key: key);

  @override
  AppProviderState createState() {
    return AppProviderState();
  }

  static AppProviderState of(BuildContext context) {
    return (context.inheritFromWidgetOfExactType(_AppProvider)
    as _AppProvider)
        .data;
  }
}
class AppProviderState extends State<AppProvider> {

  Toast toast = new Toast();

  @override
  Widget build(BuildContext context) {

    return new _AppProvider(
      data: this,
      child: widget.child,
    );
  }
}

class _AppProvider extends InheritedWidget {
  final AppProviderState data;

  _AppProvider({Key key, this.data, Widget child})
      : super(key: key, child: child);

  @override
  bool updateShouldNotify(_AppProvider old) {
    return true;
  }
}

create toast.dart paste this.


import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:testtoast/toast_widget.dart';
class Toast {

  void showFlushbar({
    String title,
    @required String message,
    @required BuildContext context,
    Duration duration,
  }) {
    if (context != null) {
      ToastWidget.of(context).showFlushbar(title ?? "No Title",message,context,duration);
    } else {
      print('Context was null, cannot show toast');
    }
  }
}

create toast_widget.dart paste this.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:another_flushbar/flushbar.dart';
class ToastWidget extends StatefulWidget {
  final Widget child;

  ToastWidget({this.child});

  @override
  ToastWidgetState createState() {
    return ToastWidgetState();
  }

  static ToastWidgetState of(BuildContext context) {
    final ToastWidgetState toastState =
    context.rootAncestorStateOfType(const TypeMatcher<ToastWidgetState>());
    return toastState;
  }
}
class ToastWidgetState extends State<ToastWidget> {

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

  @override
  Widget build(BuildContext context) {
    return _ToastInWidget(
      child: widget.child,
    );
  }

  Future showFlushbar(String title,
      String message,
      BuildContext context,
      Duration duration){
    Flushbar(
      title:  title,
      message:  message,
      duration:  duration ?? Duration(seconds: 3),
    )..show(context);
  }

}

class _ToastInWidget extends InheritedWidget {
  _ToastInWidget({Key key, Widget child}) : super(key: key, child: child);

  @override
  bool updateShouldNotify(_ToastInWidget old) {
    return true;
  }
}

Then in your main.dart do this . mind the AppProvider at the root instead of MaterialApp

@override
  Widget build(BuildContext context) {
    return AppProvider(
        child: ToastWidget(
          child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
              // This is the theme of your application.
              //
              // Try running your application with "flutter run". You'll see the
              // application has a blue toolbar. Then, without quitting the app, try
              // changing the primarySwatch below to Colors.green and then invoke
              // "hot reload" (press "r" in the console where you ran "flutter run",
              // or simply save your changes to "hot reload" in a Flutter IDE).
              // Notice that the counter didn't reset back to zero; the application
              // is not restarted.
              primarySwatch: Colors.blue,
            ),
            routes: {
              '/': (BuildContext context) {
                return HomePage();
              }
            },
          ),
        )
    );
  }

then in home page or any other page you want to use the toast just call in the build block

var providerState =  AppProvider.of(context);
var toast = providerState.toast;

toast.showFlushbar(title: "Whats Up",message: "Hello World", context: context);

example

import 'package:flutter/material.dart';
import 'package:testtoast/provider.dart';

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>{
  @override
  Widget build(BuildContext context) {
    var providerState =  AppProvider.of(context);
    var toast = providerState.toast;
    return Scaffold(
      appBar: AppBar(title: Text("Hello World")),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Hello flushbar:',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async{
          toast.showFlushbar(title: "Whats Up",message: "Hello World", context: context);
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
sm2017 commented 3 years ago

@cmdrootaccess you are using another_flushbar package,not flushbar But I will try, thanks

cdprete commented 2 years ago

I do have the same issue. The context is somehow shared, therefore when showing a Flushbar this gets pushed in the (default?) Navigator, causing a successive pop to close the message instead of, in my case, an AlertDialog.

Is there no out of the box solution from the library yet?

For now I'm doing

    // Pop until you reach the dialog
    Navigator.popUntil(
      context,
      ModalRoute.withName(AddPlaylistDialog.routeName),
    );
    // Pop the dialog itself
    Navigator.pop(context);

like also @sm2017 suggested, but it's not nice indeed.

adminant commented 1 year ago

I have the same problem, my flushbar is hidden if I call .pop() in my app to hide modal windows and so on. I want flushbar to be always on the screen. Is there any solution?