Flutter route-画面遷移

Table of Contents

Table of Contents

アプリには、画面遷移はかなり必須の部分になりますね。例えば、情報一覧から、情報の詳細に移動したり、アプリの設定画面に移動したら、ユーザー情報画面に移動するなど、使うシーンはたくさんあります。

Flutterでは、アプリのScreensやPagesはRouteで呼ばれています。各画面の移動をコントロールするのはNavigatorです。RouteNavigatorを把握できれば、簡単な画面遷移を実装出来ます。


早速、画面遷移の方法:push()pop() を紹介します。

  • ① 他の画面移動したい場合: Navigatot.push()
  • ② 元の画面に戻りたい場合: Navigator.pop()

① 他の画面移動したい場合: Navigator.push()

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => TargetWidget() // 移動先
  ),
)
MaterialPageRouteとは

A modal route that replaces the entire screen with a platform-adaptive transition.

MaterialPageRouteは各プラットフォームを対応しているルートClassです。 Androidでは、画面切り替えのアニメーションは上下進出、FadeIn,FadeOut。 iOSでは、画面切り替えのアニメーションは、左右進出。

MaterialPageRoute Constructors

MaterialPageRoute({
  @required WidgetBuilder builder,
  RouteSettings settings,
  bool maintainState: true,
  bool fullscreenDialog: false
})

デフォルトの場合、前の画面の状態をメモリに保存しますが、必要ない時に解放したいなら、maintainStateをfalseにします。

他にもCupertinoPageRouteがあります。置き換えるとiOS風のアニメーションになります。

②元の画面に戻りたい場合: Navigator.pop()


Navigator.pop(context);

Named Route

ルートは多い場合、管理は面倒になることは多いです。そのため、まとめて名前で管理すると楽になります。 ルート名前で画面を遷移するには、Navigator.pushNamed()関数を使います。

Navigator.pushNamed(context, '/second');

/second」はルートの名前です。名前の命名をアプリの作成する時に行う必要があります。下記の例では、MaterialAppを作成する時に、initailRouteroutesの値を追加します。

MaterialApp(
  initialRoute: '/',
  routes: {
    // When navigating to the "/" route, build the FirstScreen widget.
    '/': (context) => FirstScreen(),
    // When navigating to the "/second" route, build the SecondScreen widget.
    '/second': (context) => SecondScreen(),
  },
);

❗️公式ドキュメントにはhomeを使う時に注意事項があります。

Warning: When using initialRoute, don’t define a home property.

Pass arguments to a named route

下記のようにNavigator.pushNamed()関数の第三引数argmentsに遷移したい画面に渡したい値を設定できます。

Navigator.pushNamed(
      context,
      '/second',
      arguments: ScreenArguments('設定したい値'),
);


argumentsに設定したScreenArgumentsを自分で作成する必要がありますので、 遷移したい画面クラスのファイル(ex: second_screen.dart)にクラスに作成します。

// second_screen.dart

class ScreenArguments {
  final String title;
  final String message;

  ScreenArguments(this.title, this.message);
}

渡した値をScendScreenで取得したいとき、下記のようにModalRoute.of(context).settings.argumentsで取得できます。

class SecondScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final ScreenArguments args = ModalRoute.of(context).settings.arguments;

    return Scaffold(
      appBar: AppBar(
        title: Text(args.title),
      ),
      body: Center(
        child: Text(args.message),
      ),
    );
  }
}

上記の例はStatelessWidgetで紹介しました。 他にonGenerateRoute()の方法もあります。この方法を使えば、widgetの中ではなく、MaterialAppで値の取得ができます。

MaterialApp(
    ...
      onGenerateRoute: (settings) {
        print('build route for ${settings.name}');
        var routes = <String, WidgetBuilder>{
          "/": (ctx) => Home(),
          "/second": (context) {
            final ScreenArguments args = settings.arguments;
            return SecondScreen(title: args.title, message: args.message);
          }
        };
        WidgetBuilder builder = routes[settings.name];
        return MaterialPageRoute(builder: (ctx) => builder(ctx));
      },
    ....

感想

画面遷移はウェブサイトURLのように似てます。画面は多い場合、ルート名前で遷移をコントロールするメリットがありますので、今後もルート名前を使った方が良さそうです。


参考