💨

【Flutter】go_router(push)での遷移挙動

2022/11/26に公開

このページでのFlutterバージョン

go_routerとは

Flutterで利用できる画面遷移を補助するためのパッケージです。
https://pub.dev/packages/go_router
Navigator 2.0というナビゲーションシステムを開発者が意識しないようサポートしてくれます。

Navigator 1.0, 2.0などの説明は以下で勉強させていただきました
https://zenn.dev/ntaoo/articles/6641e846765da1#navigator-1.0-の課題と、navigator-2.0-の特徴

また、Flutter Favoriteと、開発元がflutter.devなので安全に使えそうなパッケージになるかと思います。

基本的な使い方

以下の流れで利用します。

1. ページを宣言する

// pathに画面のPathを設定。
// builderに遷移先のページをreturnするように設定
final router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => const TopPage(
        title: 'Top Page',
      ),
      routes: [
        GoRoute(
          path: 'create',
          builder: (context, state) => const CreatePage(
            title: 'Create Page',
          ),
        ),
      ],
    ),
    GoRoute(
      path: ('/settings'),
      builder: (context, state) => const SettingsPage(
        title: 'Settings Page',
      ),
    ),
  ],
);

2. Material Appに設定する

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router( // .routerを追加
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      // 以下3行を追加
      routeInformationProvider: router.routeInformationProvider,
      routeInformationParser: router.routeInformationParser,
      routerDelegate: router.routerDelegate,
    );
  }
}

3. 遷移してみる

TextButton.icon(
  icon: const Icon(Icons.add),
  label: const Text('CREATE PAGE'),
  onPressed: () {
    context.go('/settings'); // 引数にはPathを指定します。
  },
),

基本的な画面遷移

1. context.push

履歴を残し次の画面に遷移する方法です。
/ : TOP画面 からpushで /create : Create Pageに遷移した場合、履歴は次のようになります。

[RouteMatch(/, {}), RouteMatch(/create, {})]

履歴を確認する場合は以下の手順で確認します。

print(router.routerDelegate.currentConfiguration.matches);

また、pushで遷移した場合はAppBarをセットしている場合、デフォルトでバックキーがAppBarに表示されるようになります。

back_key

色々ためしてみる

1. ツリー外のURIにpushしてみる

上記の「基本的な使い方」の「1. ページを宣言する」にあるコードで、以下の順番でPushするとどうなるのでしょうか?

  1. / : TOP画面
  2. /create : Create Page
  3. /settings : Settings Page
結果

普通に遷移できる。
履歴的には以下のようになりました。

[RouteMatch(/, {}), RouteMatch(/create, {}), RouteMatch(/settings, {})]

Settings PageAppBarにはバックキーが表示され、バックキーをタップするとCreate Pageにpopされました。

2. 2階層先の画面にpushしてみる

Create PageroutesCreate Help Pageを追加しました。

        GoRoute(
          path: 'create',
          builder: (context, state) => const CreatePage(
            title: 'Create Page',
          ),
          routes: [
            GoRoute(
              path: 'help',
              builder: (context, state) => const CreateHelpPage(
                title: 'Create Help Page',
              ),
            ),
          ],
        ),

この状態でTOP画面からCreate Help Pageにpushしてみます。

context.go('/create/help');

履歴は以下のようになりました。

[RouteMatch(/, {}), RouteMatch(/create, {}), RouteMatch(/create/help, {})]

どうやらCreate Pageを経由してCreate Help Pageに遷移しているようです。
AppBarにBackキーが表示されており、タップしてみるとCreate Pageにpopしました。
2段階先の階層にある画面に対して、pushで遷移するとその間にある場面を履歴に残しつつ遷移するようでした。

もしCreate Pageを遷移したくない場合(例えば、TOPページがダッシュボード的な扱いで、本来一覧ページから遷移する詳細ページをTOPページから直接遷移できるときなど)は、以下のようにCreate Pageと同階層に設定する必要がありそうです。

      routes: [
        GoRoute(
          path: 'create',
          builder: (context, state) => const CreatePage(
            title: 'Create Page',
          ),
        ),
        GoRoute(
          path: 'create/help',
          builder: (context, state) => const CreateHelpPage(
            title: 'Create Help Page',
          ),
        ),
      ],

同階層に設定した場合、

context.go('/create/help');

の遷移で履歴的には次のようになり、直接遷移できるようになりました。

[RouteMatch(/, {}), RouteMatch(/create/help, {})]
3. 同じ画面にpushで遷移してみる

Top画面からTop画面にpushで遷移してみます。
遷移でき、以下のような履歴になりました。
AppBarにはバックキーが表示され、1つ目のTOP画面にpopしました。

[RouteMatch(/, {}), RouteMatch(/, {})]

同じ画面にpushで遷移することは少ないかもしれませんが、extraやqueryを変更しつつ遷移することなどに利用できそうでした。(例えば、動画サイトの動画ページからレコメンドから次の動画ページに遷移する場合など)


pushの挙動について、いろいろ試してみましたが、
replaceやpop,goなど他にもあるのでそれぞれの挙動も今後確認していこうと思います。

Discussion