简体   繁体   English

ScaffoldMessenger 抛出英雄 animation 错误

[英]ScaffoldMessenger throws a hero animation error

I am using the new ScaffoldMessenger to show a snackbar if a user successfully creates a project.如果用户成功创建项目,我将使用新的 ScaffoldMessenger 来显示小吃栏。 While showing the snackbar, i navigate the app to the dashboard.在显示快餐栏时,我将应用程序导航到仪表板。 But as soon as it hits the dashboard There are multiple heroes that share the same tag within a subtree error is thrown.但是一旦它点击仪表板就有多个英雄在子树中共享相同的标签,就会抛出错误。 I am not using any Hero widget in my dashbard and I have one FloatingActionButton but its hero parameter is set to null.我没有在仪表板中使用任何 Hero 小部件,我有一个 FloatingActionButton,但它的 hero 参数设置为 null。

Sample code:示例代码:

ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('A SnackBar has been shown.'),
          animation: null,
        ),
      );
Navigator.pushReplacementNamed(context, '/dashboard');

Which results in this error:导致此错误:

The following assertion was thrown during a scheduler callback:
There are multiple heroes that share the same tag within a subtree.

Within each subtree for which heroes are to be animated (i.e. a PageRoute subtree), each Hero must have a unique non-null tag.
In this case, multiple heroes had the following tag: <SnackBar Hero tag - Text("A SnackBar has been shown.")>

Within each subtree for which heroes are to be animated (i.e. a PageRoute subtree), each Hero must have a unique non-null tag.
In this case, multiple heroes had the following tag: <SnackBar Hero tag - Text("A SnackBar has been shown.")>

Here is the subtree for one of the offending heroes: Hero
    tag: <SnackBar Hero tag - Text("A SnackBar has been shown.")>
    state: _HeroState#7589f
When the exception was thrown, this was the stack
#0      Hero._allHeroesFor.inviteHero.<anonymous closure>
#1      Hero._allHeroesFor.inviteHero
package:flutter/…/widgets/heroes.dart:277
#2      Hero._allHeroesFor.visitor
package:flutter/…/widgets/heroes.dart:296
#3      ComponentElement.visitChildren
package:flutter/…/widgets/framework.dart:4729
#4      Hero._allHeroesFor.visitor
package:flutter/…/widgets/heroes.dart:309
...


I had the same problem.我有同样的问题。 This happens if you have nested Scaffolds.如果您有嵌套的脚手架,就会发生这种情况。 The ScaffoldMessenger wants to send the Snackbar to all Scaffolds. ScaffoldMessenger 想要将 Snackbar 发送到所有 Scaffolds。 To fix this you need to wrap your Scaffold with a ScaffoldMessenger.要解决此问题,您需要使用 ScaffoldMessenger 包裹您的 Scaffold。 This ensures you that only one of your Scaffold receives the Snackbar.这确保您只有一个 Scaffold 收到 Snackbar。

ScaffoldMessenger(
  child: Scaffold(
    body: ..
    ),
)

I ran into same problem and fixed it by removing SnackBar before any call to Navigator with ScaffoldMessenger.of(context).removeCurrentSnackBar() .我遇到了同样的问题并通过在使用ScaffoldMessenger.of(context).removeCurrentSnackBar()调用Navigator之前删除 SnackBar 来修复它。

Look like this with your Sample code:使用您的示例代码看起来像这样

ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('A SnackBar has been shown.'),
          animation: null,
        ),
      );
ScaffoldMessenger.of(context).removeCurrentSnackBar();
Navigator.pushReplacementNamed(context, '/dashboard');

Here's the link that helped me : https://flutter.dev/docs/release/breaking-changes/scaffold-messenger#migration-guide这是帮助我的链接: https : //flutter.dev/docs/release/break-changes/scaffold-messenger#migration-guide
Hope it'll work for you希望它对你有用

I resolved this by having the call run in the next event-loop iteration:我通过在下一个事件循环迭代中运行调用来解决这个问题:

Future.delayed(const Duration(), () => 
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(...)));

Had the same problem, turns out I had a scaffold widget returning another scaffold in my subtree (whoops)有同样的问题,结果我有一个脚手架小部件在我的子树中返回另一个脚手架(哎呀)

If so, then your snackbar is being popped on both scaffolds, and then initiating the transition causes the error.如果是这样,那么您的小吃店会在两个脚手架上弹出,然后启动转换会导致错误。

The answer by @GreenFrog assumes that you're handling navigation on your own, in the case you're facing this problem while using the default back button behavior of the Scaffold widget you'll need to wrap your Scaffold in a WillPopScope widget, this basically vetos requests to Navigator , moreover by using WillPopScope.onWillPop you can essentially call ScaffoldMessenger.of(context).removeCurrentSnackBar(); @GreenFrog 的答案假设您自己处理导航,如果您在使用Scaffold小部件的默认后退按钮行为时遇到此问题,您需要将Scaffold包装在WillPopScope小部件中,这基本上否决对Navigator请求,此外,通过使用WillPopScope.onWillPop您基本上可以调用ScaffoldMessenger.of(context).removeCurrentSnackBar(); just before the route is popped.就在路由弹出之前。

Example:例子:

...
WillPopScope(
    onWillPop: () async {
      ScaffoldMessenger.of(context).removeCurrentSnackBar();
      return true;
    },
    child: Scaffold(...,
  );

So this is clearly a bug in Flutter.所以这显然是 Flutter 中的一个错误。

The best "official" workaround, is to show the snack bar on the next frame:最好的“官方”解决方法是在下一帧显示小吃吧:

WidgetsBinding.instance.addPostFrameCallback((_) {
   // ... show the culprit SnackBar here.
});

But we can all agree that it shouldn't happen in the first place.但我们都可以同意,这首先不应该发生。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM