マグネテック備忘録

Flutterアプリ開発の備忘録

【Flutter】ページ遷移(go_router)



概要

  • Navigatorよりも便利にページ遷移を行うことができるみたいです。
  • ↓↓公式サイト

pub.dev



準備

パッケージの追加

dependencies:
  go_router: ^13.0.1

インポート文

import 'package:go_router/go_router.dart';





基本的な使用方法

1. GoRouter型変数の用意

  • 公式ページ:Configuration topic - Dart API
  • アプリを立ち上げたときに表示する「MyApp」と移動先のページの「Page1」を作成。
  • とりあえず、GoRouter型の変数にroutesにページの情報を記載すればよいみたいです。
  • ページはpathかname指定で移動できます(移動方法は後述)。
  • 初めに読み込みたいページのpathは「/」にします
final goRouter = GoRouter(

  routes: [
    // 初期ページ
    GoRoute(
      path: '/',
      pageBuilder: (context, state) {
        return MaterialPage(
          key: state.pageKey,
          child: const MyApp(),
        );
      },
    ),

    // ページ1
    GoRoute(
      name: 'page1_name',
      path: '/page1',
      pageBuilder: (context, state) {

        // ページを渡す
        return MaterialPage(
          key: state.pageKey,
          child: const Page1(),
        );
      },
    ),
  ],
);



2. goRouterを組み込む

  • 先ほど指定したgoRouterを使えるようにするために、以下の指定を行ったMaterialAppを用意してrunAppします。
MaterialApp app = MaterialApp.router(
    routerConfig: goRouter,
);



3. ページ遷移の方法

  • 大きく分けて、(1)push or go(2)name or pathと2つの軸で呼び出し方を設定できます。
  • (1) push or go:での遷移は現在のページの上に呼び出したいページを表示するため、戻るボタンで前のページに簡単に戻れます。一方、goでの遷移は完全に移動してしまうので前のページには戻れなくなるみたいです。
  • (2) name or path:GoRouteのnameとpathのどちら指定で移動するかを決定します。
  • 合計4種類の移動方法があるそうなので、場面に応じて使い分けます(表参照)。
  • 例)pushでpath「/page1」に移動するとき:context.push('/page1');
  • また、pushでの移動後に元のページに戻る際は、ページの上側にある矢印 or context.pop()で戻れます
push(前のページに戻れる) go(完全に移動)
name指定 pushNamed goNamed
path指定 push go





ページにパラメータを渡したいとき

ざっくり言うと、pushNamed or goNamedで遷移して、queryParametersに渡したい変数をMapとして指定すればOKみたいです。
例えば、ページ名「page2_name」にid(int型)とuser(String型)を渡す場合は、

context.pushNamed('page2_name', queryParameters: {'id':'6', 'user': 'Mike'});

とすればよいです。

これを受け取る場合は、page2_nameを指定したGoRoute内のpageBuilderで

pageBuilder: (context, state) {

  // クエリを取得
  final mp = state.uri.queryParameters;

  // パラメータを取得
  int id = json.decode(mp['id']!);
  String user = mp['user']!;
}

とすればよいです。

サンプルコードなどを載せると長くなるため、別の記事にまとめました。
良かったら参考にしてください↓↓(露骨な宣伝)
magnetech.hatenablog.com




デモアプリ

サンプルコード

router.dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'my_app.dart';
import 'page1.dart';

final goRouter = GoRouter(

  routes: [
    // 初期ページ
    GoRoute(
      path: '/',
      pageBuilder: (context, state) {
        return MaterialPage(
          key: state.pageKey,
          child: const MyApp(),
        );
      },
    ),

    // ページ1
    GoRoute(
      name: 'page1_name',
      path: '/page1',
      pageBuilder: (context, state) {

        // ページを渡す
        return MaterialPage(
          key: state.pageKey,
          child: const Page1(),
        );
      },
    ),
  ],
);


main.dart

import 'package:flutter/material.dart';
import 'router.dart';

void main() {

  MaterialApp app = MaterialApp.router(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      routerConfig: goRouter,
  );

  runApp(app);
}


my_app.dart

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('MyApp'),
      ),
      
      body: Center(
        child: Column(
          // mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[

            ElevatedButton(
              onPressed: (){
                context.push('/page1');
              },
              child: const Text("context.push('/page1') \n→ path指定で現在ページの上にPage1を重ねる")
            ),
            ElevatedButton(
              onPressed: (){
                context.go('/page1');
              },
              child: const Text("context.go('/page1') \n→ path指定でPage1に移動")
            ),
            ElevatedButton(
              onPressed: (){
                context.pushNamed('page1_name');
              },
              child: const Text("context.pushNamed('page1_name') \n→ name指定で現在ページの上にPage1を重ねる")
            ),
            ElevatedButton(
              onPressed: (){
                context.goNamed('page1_name');
              },
              child: const Text("context.goNamed('page1_name') \n→ name指定でPage1に移動")
            ),
          ],
        ),
      ),
    );
  }
}


page1.dart

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('Page1'),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            ElevatedButton(
              onPressed: (){
                context.pop();
              },
              child: const Text('context.pop()')
            ),
            ElevatedButton(
              onPressed: (){
                context.go('/');
              },
              child: const Text("context.go('/')")
            ),
          ],
        ),
      ),
    );
  }
}



実行例

初期ページ

  • my_app.dartで指定したページを読み込みます。

my_app

push or pushNamedをしたとき

  • pushのときは先ほどのページの上に重ねているので、上側の矢印 or pop()で戻れます

pushで移動したとき

go or goNamedをしたとき

  • goのときはページを上書きしているので、pop()では戻れませんし、上側の矢印もありません

goで移動したとき