Search code examples
androidiosflutterdartflutter-go-router

Another exception was thrown: Duplicate GlobalKey detected in widget tree - StatefulShellRoute


I tried to add route transition animation with AnimatedSwitcher to StatefulShellRoute.indexedStack but got this error:

flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown while finalizing the widget tree:
flutter: Duplicate GlobalKey detected in widget tree.
flutter: The following GlobalKey was specified multiple times in the widget tree. This will lead to parts of
flutter: the widget tree being truncated unexpectedly, because the second time a key is seen, the previous
flutter: instance is moved to the new location. The key was:
flutter: - [LabeledGlobalKey<StatefulNavigationShellState>#c2de3]
flutter: This was determined by noticing that after the widget with the above global key was moved out of its
flutter: previous parent, that previous parent never updated during this frame, meaning that it either did
flutter: not update at all or updated before the widget was moved, in either case implying that it still
flutter: thinks that it should have a child with that global key.
flutter: The specific parent that did not update after having one or more children forcibly removed due to
flutter: GlobalKey reparenting is:
flutter: - SizedBox-[<'0'>](renderObject: RenderConstrainedBox#33176 relayoutBoundary=up4)
flutter: A GlobalKey can only be specified on one widget at a time in the widget tree.
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:3109:15)
flutter: #1      BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:3134:8)
flutter: #2      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:919:19)
flutter: #3      RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:360:5)
flutter: #4      SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1297:15)
flutter: #5      SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1227:9)
flutter: #6      SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1085:5)
flutter: #7      _invoke (dart:ui/hooks.dart:170:13)
flutter: #8      PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:401:5)
flutter: #9      _drawFrame (dart:ui/hooks.dart:140:31)
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
flutter: Another exception was thrown: Duplicate GlobalKey detected in widget tree.

Code:

return Scaffold(
  body: AnimatedSwitcher(
    duration: const Duration(milliseconds: 500),
    switchInCurve: Curves.ease,
    switchOutCurve: Curves.ease,
    child: SizedBox(
      key: Key(navigationShell.currentIndex.toString()),
      child: navigationShell,
    ),
  ),
  ....

Every time I call navigationShell.goBranch I get this error:

flutter: Another exception was thrown: Duplicate GlobalKey detected in widget tree.

I want there to be a page transition animation. I couldn't find any solutions.


Solution

  • Solved!

    I tried adding layoutBuilder to AnimatedSwitcher and it works without errors.

    Code:

        return Scaffold(
          body: AnimatedSwitcher(
            duration: const Duration(milliseconds: 500),
            switchInCurve: Curves.ease,
            switchOutCurve: Curves.ease,
            layoutBuilder: (currentChild, previousChildren) {
              return currentChild!;
            },
            child: SizedBox(
              key: ValueKey(navigationShell.currentIndex),
              child: navigationShell,
            ),
          ),