Go Router StatefulShellRoute.indexedStack CupertinoTabScaffold GlobalKey 예외 처리 기록

문법을 틀리지 않았고 Global Key도 별도 할당하지 않았는데, 매번 Global Key 관련 에러가 발생해 해결 방법을 찾아보았다.

 

https://github.com/flutter/flutter/issues/113757

확인해보니, indexedStack은 Material에서만 정상동작을 지원한다는 내용.

Cupertino계열은 해당 위젯 자체가 별도의 stack을 생성하고 관리하므로

LabeledGlobalKey<StatefulNavigationShellState>

역시 자동으로 생성되는 것이다.

 

CupertinoTabScaffold 위젯에 매번 index로 value key를 할당해주어 해당 부분을 해결할 수 있었지만

이는 각 페이지 라우팅 시에 매번 바텀시트를 불필요하게 재렌더링하는 문제가 발생한다.

 

따라서 해당 부분을 해결하기 위해 한 유저가 

https://github.com/flutter/packages/pull/7583/commits/959165c2e5258767af8596c4ef5a6365ca0ffd47

 

[go_router] Fixed TabView swiping in custom stateful shell route example by tolo · Pull Request #7583 · flutter/packages

Updated custom_stateful_shell_route.dart example to better support swiping in TabView. Also added code to demonstrate use of PageView instead of TabView. Note that to be fully effective from a usab...

github.com

이 커밋에 예시를 올려주었다.

 

StatefulShellRoute(
  builder: (context, state, navigationShell) {
    return navigationShell;
  },
  navigatorContainerBuilder: (context, navigationShell, children) =>
      BottomTabBarLayout(
    navigationShell: navigationShell,
    children: children,
  ),

 

class BottomTabBarLayout extends StatefulWidget {
  const BottomTabBarLayout({
    required this.navigationShell,
    super.key,
    required this.children,
  });

  final StatefulNavigationShell navigationShell;
  final List<Widget> children;
  @override
  State<BottomTabBarLayout> createState() => _BottomTabBarLayoutState();
}

class _BottomTabBarLayoutState extends State<BottomTabBarLayout> {
  late final CupertinoTabController tabController =
      CupertinoTabController(initialIndex: widget.navigationShell.currentIndex);
  @override
  void dispose() {
    tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return CupertinoTabScaffold(
      controller: tabController,
      tabBar: BottomTabBar(
          currentIndex: widget.navigationShell.currentIndex,
          changeIndex: (index) {
            widget.navigationShell.goBranch(index,
                initialLocation: index == widget.navigationShell.currentIndex);
          }),
      tabBuilder: (context, index) {
        return widget.children[index];
      },
    );
  }
}

내 코드에 적용한 것이라 changeIndex는 onTap메소드로 보면 된다.

차이점은 탭빌더에서 navigationShell을 반환하지 않아 중복되는 Stack을 생성하지 않는 것이다.

이를 통해 자체적으로 stack을 관리하는 cupertinotabscaffold의 역할을 침해하지 않고 go router의 기능을 사용하여 좀 더 효과적인 코딩을 할 수 있다.

 

children은 branches의 역할을 한다고 보면 된다.

반응형
LIST

'Flutter' 카테고리의 다른 글

인포챗 개발기 - Flutter 의존성 세팅  (0) 2024.09.26