简体   繁体   中英

ScaffoldMessenger throws a hero animation error

I am using the new ScaffoldMessenger to show a snackbar if a user successfully creates a project. 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.

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. To fix this you need to wrap your Scaffold with a ScaffoldMessenger. This ensures you that only one of your Scaffold receives the 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() .

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
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(); 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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