플러터/Packages

[Package] go_router를 사용한 화면 이동

sam-ss 2024. 4. 22. 02:35

go_router 란?

애플리케이션 내에서 라우팅 및 탐색을 처리하는 데 사용되는 패키지

기본 셋팅

pubspec.yaml 에 추가

dependencies:
  go_router: ^13.2.4

 

router.dart 추가

// router.dart

final router = GoRouter(
  routes: [
    GoRoute(path: '/', builder: (context, state) => const MainPage()),
    GoRoute(
      name: "Home",
      path: "/home",
      builder: (context, state) {
        return const HomePage();
      },
    )
  ],
);

 

main.dart 수정

  • MaterialApp.router로 수정
  • routerConfig 추가
// main.dart

void main() {
  runApp(const _App());
}

class _App extends StatelessWidget {
  const _App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: router,
    );
  }
}

화면 이동 방법

이동 함수

  • go : 페이지 대체
  • push : 페이지 스택에 푸시
  • pushReplacement : 페이지 스택의 가장 위에 있는 페이지를 대체
  • replace : 페이지 스택의 가장 위에 있는 페이지와 교체, 페이지 키가 재사용되서 상태를 보존하고 페이지 애니메이션을 실행하지 않음
  • ..Named : GoRoute 내부에 있는 name을 사용하여 이동
context.go('/home'); 
context.goNamed('Home')

context.push('/home')
context.pushNamed('Home')

context.replace('/home')
context.replaceNamed('Home')

context.pushReplacement('/home')
context.pushReplacementNamed('Home')

context.go(context.namedLocation('Home'));

 

사용 예시

// 사용 예시
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            OutlinedButton(
                onPressed: () {
                  context.push('/first');
                },
                child: Text("1")),
            OutlinedButton(
                onPressed: () {
                  context.push('/second');
                },
                child: Text("2"))
          ],
        ));
  }
}

화면 이동 - Path 파라미터

GoRoute(
  path: '/home/:id',
  builder: (BuildContext context, GoRouterState state) =>
      HomePage(id: state.pathParameters['id']!),
),

// 화면 이동
context.go("/home/hi");

화면 이동 - Query 파라미터

GoRoute(
  path: '/home',
  builder: (context, state) {
    return HomePage(id: state.uri.queryParameters['id']!);
  },
),

// 화면 이동
context.go('/home?id=hi');

화면 이동 - extra 데이터

객체 데이터를 넘길수도 있다. 

GoRoute(
  path: "/home",
  builder: (context, state) {
    final id = (state.extra as Map)['id'] as String;
    return HomePage(id: id);
  }
),

// 화면 이동
context.push('/home', extra: {
  "id": "hi"
});

ShellRoute

다수의 Navigator이동에 사용

화면 구조

-> Scaffold with Bottom Navigation Bar
   -> First page
   -> Second page
   -> Third page

 

router 선언

final GlobalKey<NavigatorState> rootNavKey = GlobalKey<NavigatorState>();
final GlobalKey<NavigatorState> projectNavKey = GlobalKey<NavigatorState>();

final GoRouter router = GoRouter(
  navigatorKey: rootNavKey,
  initialLocation: "/",
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return const HomePage();
      },
    ),
    
    ShellRoute(
      parentNavigatorKey: rootNavKey,
      navigatorKey: projectNavKey,
      builder: (context, state, child) => GnbScaffold(state: state, child: child),
      routes: [
        GoRoute(
          path: '/first',
          builder: (context, state) {
            return const FirstPage();
          },
        ),
        GoRoute(
          path: '/second',
          builder: (context, state) {
            return const SecondPage();
          },
        ),
        GoRoute(
          path: '/third',
          builder: (context, state) {
            return const ThirdPage();
          },
        ),
      ],
    )
  ],
);

 

bottomNavigationBar 가지는 화면

class GnbScaffold extends StatefulWidget {
  final GoRouterState state;
  final Widget child;

  const GnbScaffold(
      {required this.state, required this.child, super.key});

  @override
  State<GnbScaffold> createState() => _GnbScaffoldState();
}

class _GnbScaffoldState extends State<GnbScaffold> {
  int currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: widget.child,
      bottomNavigationBar: BottomNavigationBar(
        onTap: changeTab,
        currentIndex: currentIndex,
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: 'first'),
          BottomNavigationBarItem(icon: Icon(Icons.ac_unit), label: 'second'),
          BottomNavigationBarItem(icon: Icon(Icons.access_time_filled), label: 'third'),
        ],
      ),
    );
  }

  void changeTab(int index) {
    switch(index){
      case 0:
        context.go('/first');
        break;
      case 1:
        context.go('/second');
        break;
      default:
        context.go('/third');
        break;
    }
    setState(() {
      currentIndex = index;
    });
  }
}

 

네이게이션 화면으로 이동.

context.push('/first');

 

위와 같이 사용하면 쉽게 화면 이동이 가능하다.