Flutter - BottomNavigationBar with go_router (navigator)

Routine·2023년 7월 20일
3

Flutter

목록 보기
1/7
post-thumbnail

해당 글은 BottomNavigationBar 와 go_router 를 사용하는것을 기준으로 한다.

go_router 왜 사용하는가?

  1. Flutter 에서 직접 관리하는 package 이다. (Flutter 업데이트로 인한 지원이나 호환성 걱정이 없다)
  2. 앱 구조를 설계하다보면 Navigation 의 복잡함과 기본 Navigator 기능 부족으로 인한 한계성.
  3. 코드가 복잡해진다.. 여러 상황의 router 관리 어떻게 하죠?
    ...등등

BottomNavigationBar 의 문제점

  1. 탭 끼리의 페이지 전환이 페이지 전환이 아니다.. (BottomNavigationBar 가 같이 넘어가요!!)
  2. 각 탭의 라우팅 관리는 어떻게 하죠? (각 탭의 route 독립적으로 살아있나요?)
  3. 위의 문제로 직접 custom 하게 되는데.. (최적화 늪으로 빠진겁니다)
    ..등등

아무튼 여러 사유들이 있겠지만 위와 같이 문제점들이 상당히 많았다.
go_router 와 BottomNavigationBar 을 같이 사용할려 하니 더욱 문제였다.
그리고 go_router 7.1.0 버전 (2023.5.22) 에서 StatefulShellRoute 이 도입되었다.

StatefulShellRoute

병렬 트리(branch 개념)에 대해 별도의 내비게이터를 생성하여 상태 저장, 탐색할 수 있다.
(각 탭에 대해 탐색 상태가 있는 BottomNavigationBar 를 구현할 때 편리하다.)

기본적인 BottomNavigationBar 를 구현할때는 StatefulShellRoute.indexedStack 메서드를
커스텀하고 싶다면 StatefulShellRoute 메서드를 사용하면 된다.

아래 소스와 같이 StatefulShellRoute 를 사용하여 router 를 구성할 수 있다.

final GoRouter _router = GoRouter(
  initialLocation: '/a',
  routes: <RouteBase>[
    StatefulShellRoute.indexedStack(
      builder: (BuildContext context, GoRouterState state,
          StatefulNavigationShell navigationShell) {
        // 사용자 정의 셸을 구현하는 위젯을 반환합니다. (BottomNavigationBar)
        return Scaffold(
			body: navigationShell,
      		bottomNavigationBar: BottomNavigationBar(
	        items: const <BottomNavigationBarItem>[
	          BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Section A'),
    	      BottomNavigationBarItem(icon: Icon(Icons.work), label: 'Section B'),
        	  BottomNavigationBarItem(icon: Icon(Icons.tab), label: 'Section C'),
	        ],
    	    currentIndex: navigationShell.currentIndex,
        	onTap: (int index) {
            	// 브랜치를 전환하는데는 StatefulNavigationShell.goBranch 메서드를 사용한다.
            	navigationShell.goBranch(index: index);
            },
	      ),
    	);
      },
      
      // 각각 별도의 상태 저장 분기를 생성하기 위해 StatefulShellBranch 메서드를 사용한다.
      branches: <StatefulShellBranch>[
      	// Tab A (First Tab)
        StatefulShellBranch(
          routes: <RouteBase>[
            GoRoute(
              path: '/a',
              builder: (BuildContext context, GoRouterState state) =>
              const RootScreen(label: 'A', detailsPath: '/a/details'),
              routes: <RouteBase>[
                GoRoute(
                  path: 'details',
                  builder: (BuildContext context, GoRouterState state) =>
                  const DetailsScreen(label: 'A'),
                ),
              ],
            ),
          ],
        ),

        // Tab B (Second Tab)
        StatefulShellBranch(
          routes: <RouteBase>[
            GoRoute(
              path: '/b',
              builder: (BuildContext context, GoRouterState state) =>
              const RootScreen(
                label: 'B',
                detailsPath: '/b/details/1',
                secondDetailsPath: '/b/details/2',
              ),
              routes: <RouteBase>[
                GoRoute(
                  path: 'details/:param',
                  builder: (BuildContext context, GoRouterState state) =>
                      DetailsScreen(
                        label: 'B',
                        param: state.pathParameters['param'],
                      ),
                ),
              ],
            ),
          ],
        ),

        // Tab C (Third Tab)
        StatefulShellBranch(
          routes: <RouteBase>[
            GoRoute(
              path: '/c',
              builder: (BuildContext context, GoRouterState state) =>
              const RootScreen(
                label: 'C',
                detailsPath: '/c/details',
              ),
              routes: <RouteBase>[
                GoRoute(
                  path: 'details',!
                  builder: (BuildContext context, GoRouterState state) =>
                      DetailsScreen(
                        label: 'C',
                        extra: state.extra,
                      ),
                ),
              ],
            ),
          ],
        ),
      ],
    ),
  ],
);

0개의 댓글