【Flutter】go_routerの導入手順

■ルーティング
画面遷移を一元管理するための仕組み。
(ユーザーの操作に対してどの画面を表示するかを管理する仕組み)

- Navigator1.0: Navigator.push/popをするだけ。コードが複雑化
- Navigator2.0: pages[], onPopPageなどを使う。ページの状態を一元的に管理し、状態に応じて遷移を制御
- go_router: Navigator2.0をラップして使いやすくしたもの。GoRoute(),routes[],redirectなど。googleも推奨している

■導入手順

pubspec.yamlのdependenciesにgo_routerを追加し、Pub getボタンを押す
（or ターミナルから「flutter pub add go_router」と打つと自動でpubspec.yamlに追記される）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136142/42d8f4b2-fc19-9082-1e52-7faeaabf9e20.png)

サンプルコード

```dart main.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

bool isFirstPage = false;
final _router = GoRouter(routes: [
  GoRoute(
    path: '/',
    builder: (context, state) => const HomeScreen(),
  ),
  GoRoute(
    path: '/details1',
    builder: (context, state) => const DetailsScreen(title: '詳細ページ1'),
  ),
  // GoRoute(
  //   path: '/details2',
  //   builder: (context, state) => const DetailsScreen(title: '詳細ページ2'),
  // ),
  GoRoute(
    path: '/details2',
    //----------------------------------------------------------
    // スライドトランジションのカスタム (下から上）
    pageBuilder: (BuildContext context, GoRouterState state) {
      return CustomTransitionPage<void>(
        child: const DetailsScreen(title: '詳細ページ2'),
        transitionDuration: const Duration(milliseconds: 500),
        transitionsBuilder: (BuildContext context, Animation<double> animation,
            Animation<double> secondaryAnimation, Widget child) {
          return SlideTransition(
            //スライドトランジション (下から上へのスライド)
            position: Tween<Offset>(
              // begin: const Offset(1.0, 0.0),//右からから左
              begin: const Offset(0.0, 1.0), //下から上
              end: Offset.zero,
            ).animate(animation),
            child: child,
          );
        },
      );
    },
    //----------------------------------------------------------
  ),
  // /detailsでアクセスされたら、isFirstPageの値によって/details1か/details2にリダイレクト
  GoRoute(
    path: '/details',
    redirect: (BuildContext context, GoRouterState state) {
      if (isFirstPage) {
        return '/details1';
      } else {
        return '/details2';
      }
    },
  ),
]);

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

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

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('ホーム画面')),
      body: Center(
        child: ElevatedButton(
          // デフォルト
          // onPressed: () => context.go('/details'),
          // プッシュ遷移
          onPressed: () => context.push('/details'),
          child: const Text('詳細画面へ移る'),
        ),
      ),
    );
  }
}

class DetailsScreen extends StatelessWidget {
  const DetailsScreen({super.key, required this.title});

  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(
        // child: ElevatedButton(onPressed: () => context.go('/'),
        child: ElevatedButton(
          onPressed: () => context.pop(),
          child: const Text('ホーム画面へ移る'),
        ),
      ),
    );
  }
}

```