ScaffoldMessenger 不会在导航器弹出窗口中隐藏小吃栏

时间:2021-03-10 06:07:56

标签: flutter

当我使用旧的api来显示snackbar时,当用户返回上一页时,snackbar曾经消失。

使用新的 ScaffoldMessenger.of(context).showSnackBar(),小吃店保持可见。

此外,当我添加用于删除小吃店的小吃店操作时,按下 hide 操作,在返回上一页后不会隐藏小吃店。

如何在用户离开当前页面后移除零食栏?

void _successSnackbar(BuildContext context, String message) {
  ScaffoldMessenger.of(context).hideCurrentSnackBar();

  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(
      content: Row(
        children: [
          Icon(FontAwesomeIcons.checkCircle, color: Colors.green[400], size: 35),
          const SizedBox(width: 15),
          Flexible(child: Text(message, style: TextStyle(color: Colors.green[400], fontSize: 14.5))),
        ],
      ),
      action: SnackBarAction(
        label: 'Hide',
        onPressed: () {
          ScaffoldMessenger.of(context).hideCurrentSnackBar();
        },
      ),
      duration: Duration(seconds: 2),
    ),
  );

2 个答案:

答案 0 :(得分:3)

您可以在下面复制粘贴运行完整代码
原因
来自官方文档https://flutter.dev/docs/release/breaking-changes/scaffold-messenger
ScaffoldMessenger 创建了一个作用域,所有后代 Scaffolds 在其中注册以接收 SnackBars这就是它们在这些转换中持久化的方式
所以在你的情况下,ScaffoldMessenger 提供的根 MaterialApp 让所有后代 Scaffolds 收到 SnackBars

解决方案
除非在树的更下方创建新的 ScaffoldMessenger 范围。通过实例化您自己的 ScaffoldMessenger,您可以控制哪些 Scaffolds 接收 SnackBars
要在从第二页弹出时自动隐藏 SnackBar,您可以在第二页用 Scaffold 换行 ScaffoldMessenger,在我的示例中还需要 Builder

Page2 中的代码片段

Widget build(BuildContext context) {
    return ScaffoldMessenger(
      child: Scaffold(
         ...
            child: Column(
              children: [
                Text("Second route"),
                Builder(builder: (BuildContext context) {
                  return ElevatedButton(
                      onPressed: () {
                        _successSnackbar(context, "messge of page 2");
                      },
                      child: Text('show message'));
                }),

工作演示

enter image description here

完整代码

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Page 1',
            ),
            ElevatedButton(
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => Page2()),
                  );
                },
                child: Text('Go to page 2'))
          ],
        ),
      ),
    );
  }
}

class Page2 extends StatefulWidget {
  @override
  _Page2State createState() => _Page2State();
}

class _Page2State extends State<Page2> {
  void _successSnackbar(BuildContext context, String message) {
    ScaffoldMessenger.of(context).hideCurrentSnackBar();

    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Row(
          children: [
            Icon(Icons.check, color: Colors.green[400], size: 35),
            const SizedBox(width: 15),
            Flexible(
                child: Text(message,
                    style:
                        TextStyle(color: Colors.green[400], fontSize: 14.5))),
          ],
        ),
        action: SnackBarAction(
          label: 'Hide',
          onPressed: () {
            ScaffoldMessenger.of(context).hideCurrentSnackBar();
          },
        ),
        duration: Duration(seconds: 20),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return ScaffoldMessenger(
      child: Scaffold(
          appBar: AppBar(
            title: Text("page 2"),
          ),
          body: Center(
            child: Column(
              children: [
                Text("Second route"),
                Builder(builder: (BuildContext context) {
                  return ElevatedButton(
                      onPressed: () {
                        _successSnackbar(context, "messge of page 2");
                      },
                      child: Text('show message'));
                }),
                ElevatedButton(
                    onPressed: () {
                      Navigator.pop(
                        context,
                      );
                    },
                    child: Text('Pop'))
              ],
            ),
          )),
    );
  }
}

答案 1 :(得分:0)

直接通过 scaffoldMessenger 代替传递上下文和寻找 ScaffoldMessenger:

void _successSnackbar(ScaffoldMessengerState scaffoldMessengerState , String message) {
  scaffoldMessengerState.hideCurrentSnackBar();

  scaffoldMessengerState.showSnackBar(
    SnackBar(
      content: Row(
        children: [
          Icon(FontAwesomeIcons.checkCircle, color: Colors.green[400], size: 35),
          const SizedBox(width: 15),
          Flexible(child: Text(message, style: TextStyle(color: Colors.green[400], fontSize: 14.5))),
        ],
      ),
      action: SnackBarAction(
        label: 'Hide',
        onPressed: () {
          scaffoldMessengerState.hideCurrentSnackBar();
        },
      ),
      duration: Duration(seconds: 2),
    ),
  );

要在页面弹出时自动关闭小吃店,您必须放置一个 scaffoldMessengerState.hideCurrentSnackBar();在 will pop 回调中或在导航器观察者中

相关问题