【问题标题】:Flutter: How to display a snackbar from an appbar actionFlutter:如何从 appbar 动作中显示快餐栏
【发布时间】:2019-04-30 19:21:58
【问题描述】:

在执行来自AppBar 的操作后,我试图显示SnackBarAppBar 无法从构建器构建,因此它无法访问 Scaffold 祖先。 我知道我们可以随时使用GlobalKey 对象来访问上下文,但我想知道是否有不使用GlobalKey 的解决方案。 我发现了一些 github 问题和 pull-request,但我无法从他们那里找到解决方案 => https://github.com/flutter/flutter/issues/4581https://github.com/flutter/flutter/pull/9380

更多上下文: 我有一个Appbar 和一个PopupMenuButton,它们有一个项目。当用户单击此项目时,我会显示一个对话框,其中 showDialog 方法,如果用户单击“确定”,我想显示一个 SnackBar

【问题讨论】:

    标签: dart flutter android-snackbar snackbar


    【解决方案1】:

    您可以使用 Builder 小部件

    例子:

    Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          Builder(
            builder: (BuildContext context) {
              return IconButton(
                icon: const Icon(Icons.message),
                onPressed: () {
                  final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
                  Scaffold.of(context).showSnackBar(snackBar);
                },
              );
            },
          ),
        ],
      )
    );
    

    【讨论】:

    • 这就是我要找的东西
    【解决方案2】:

    Scaffold.appBar 参数需要一个PreferredSizeWidget,所以你可以有一个Builder 像这样:

    appBar: PreferredSize(
      preferredSize: Size.fromHeight(56),
      child: Builder(
        builder: (context) => AppBar(...),
      ),
    ),
    

    【讨论】:

    • 我尝试了您的解决方案,但是当我将上下文传递给构建警报的方法时,然后当我尝试显示 SnackBar 时,在此上下文中,我仍然有 Scaffold.of() called with a context that does not contain a Scaffold 错误。
    • 这个解决方案对我有用。我的电话:操作:[ new IconButton(icon: const Icon(Icons.settings), onPressed: () =>_handleSettings(Scaffold.of(context))), ],
    • 按原样运行,builder: (context) =&gt; AppBar(...),:确保您将 AppBar 代码写在括号内。如果您将 AppBar 提取到变量或方法中,它将停止工作。
    【解决方案3】:

    一个选项是在对话框中使用两个上下文,并使用传递给对话框的上下文来搜索Scaffold

    当你显示一个对话框时,你显示的是一个完全不同的页面/路由,它超出了调用页面的范围。所以没有脚手架。

    下面是一个使用第一页范围的工作示例。 但是,问题在于 SnackBar 没有被删除。

    如果您改为使用GlobalKey 来获取Scaffold,问题是一样的。

    在这种情况下,我会考虑不使用 Snackbar,因为它与下面的页面相关联。它甚至被对话框阴影变灰。

    import 'package:flutter/material.dart';
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          home: new MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      _showDialog(BuildContext context1) {
        return showDialog(
            context: context1,
            builder: (BuildContext context) {
              return AlertDialog(
                content: Text("Dialog"),
                actions: <Widget>[
                  new FlatButton(
                    child: new Text("OK"),
                    onPressed: () => Scaffold.of(context1).showSnackBar(SnackBar(
                          content: Text("Pressed"),
                        )),
                  ),
                ],
              );
            });
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text("Test"),
            actions: <Widget>[
              PopupMenuButton(
                itemBuilder: (BuildContext context) {
                  return <PopupMenuEntry>[
                    PopupMenuItem(
                      child: ListTile(
                        title: Text('Show dialog'),
                        onTap: () => _showDialog(context),
                      ),
                    ),
                  ];
                },
              )
            ],
          ),
        );
      }
    }
    

    【讨论】:

    • 我为我的问题添加了更多上下文。我没有测试您的解决方案,但我想在来自 PopupMenuButton 项目的对话后显示 SnackBar
    • 我已根据您提供的附加信息更改了答案。
    • 我测试过了。由于一些奇怪的行为,我找不到将它与我的代码集成的方法,但它正在工作。但是有几个问题:SnackBar 没有消失,动作菜单也没有自行消失。
    猜你喜欢
    • 2018-06-03
    • 2020-11-04
    • 2019-10-25
    • 2020-12-12
    • 2021-08-04
    • 1970-01-01
    • 2016-07-31
    • 2019-04-15
    • 1970-01-01
    相关资源
    最近更新 更多