Flutter如何在任何BuildContext上绘制Flushbar

5
我使用flushbar来向用户显示应用内通知,但我认为这个问题适用于任何想要覆盖当前屏幕的小部件,比如Snackbar。

我希望能够显示一个独立于屏幕间导航的通知,也就是说,如果用户在屏幕之间导航,通知应该留在所有屏幕上。因为Flushbar通知仅在当前BuildContext上绘制,所以当用户关闭当前屏幕时,通知也会消失(因为通知小部件是该屏幕小部件子树的一部分)。

有没有一种方法可以在整个应用程序的顶部显示小部件(如通知),而不管导航如何?

EDIT1:添加了示例代码。

import 'package:flushbar/flushbar_route.dart' as route;
import 'package:flushbar/flushbar.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FirstScreen(),
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('go to second screen'),
          onPressed: () {
            Navigator.of(context).push(
              MaterialPageRoute(builder: (BuildContext context) => SecondScreen())
            );
          },
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {

  final Flushbar _flushbar = Flushbar(message: 'Flushbar Notification');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Screen'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('show flushbar'),
          onPressed: () {
            showFlushbar(_flushbar, context);
          },
        ),
      ),
    );
  }
}

Future showFlushbar(Flushbar instance, BuildContext context) {
  final _route = route.showFlushbar(
    context: context,
    flushbar: instance,
  );

  return Navigator.of(context, rootNavigator: true).push(_route);
}


结果将如下所示(当返回到第一个屏幕时,我希望通知仍停留在屏幕上):

example app demo

编辑2: George的解决方案可行。此外,使用覆盖层也可能是其他人的适当解决方案(请参见这篇博客文章),即,即使在路由导航期间,覆盖层仍保持在屏幕上。但是,在我的情况下,覆盖层解决方案不太优雅,因为它不允许flushbar被解除或动画化(或者至少不是那么简单)。
相关问题:Flutter - 应用程序范围通知
2个回答

2
尝试从根Navigator中显示Flushbar。
查看flushbar库的源代码,我们可以通过导入package:flushbar / flushbar_route.dart中的showFlushbar方法来创建自己的Flushbar路线。
例如:
import 'package:flushbar/flushbar_route.dart' as route;

// ...

Future showFlushbar(Flushbar instance) {
  final _route = route.showFlushbar(
    context: context,
    flushbar: instance,
  );

  return Navigator.of(context, rootNavigator: true).push(_route);
}

更新

感谢您在问题中添加的代码。

我认为,最终的解决方案是在MaterialApp内部创建另一个Navigator - 一种第二个“子根”导航器。

现在,您可以根据需要选择2层Navigator之间的区别。

Navigator.of(context,rootNavigator:true)将返回顶级导航器 - 将其用于Flushbar或任何其他模态弹出窗口,以使其始终保持在所有屏幕的上方。

Navigator.of(context),其中rootNavigator默认为false。使用它来获取“子根”导航器以显示新屏幕/页面。

例如,在MaterialApp中放置另一个Navigator

MaterialApp(
  home: Navigator( // 'sub-root' navigator. Second in the hierarchy.
    onGenerateRoute: (_) => MaterialPageRoute(
      builder: (_) => FirstScreen(),
      settings: RouteSettings(isInitialRoute: true),
    ),
  ),
);

请告诉我这是否有帮助。

谢谢你的回答,George!不幸的是,这对我没有用。Flushbar被推到了当前屏幕的顶部,但是一旦当前屏幕(路由)被关闭(Navigator.of(context).pop()),它也会关闭Flushbar(可能是因为当前屏幕的所有子路由也从导航器中弹出)。 - chris
@chris 请在你的问题中加入一些代码 - 你是如何初始化Flushbar的,以及何时/何地调用.pop()函数。 - George Zvonov
我在我的问题中添加了一些代码,其中已经包含了你的答案。在这个例子中,我没有显式地调用.pop(),但是当点击appBar上的返回按钮时,问题是相同的。 - chris

-2

这对我有用。

当我返回上一个屏幕时,刷新消息将显示在上一个屏幕上。

onPressed: () {
   Navigator.pop(context);
   Flush.showGoodFlushbar(context, 'login successful!');
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接