2021/3/14 : Flutter : Pass arguments to a named routeの訳

まとめ

(A)MaterialAppのroutesプロパティでルートテーブル指定+ModalRoute.ofで受け取る方法。

(B)MaterialAppのonGenerateRouteプロパティでルートテーブル指定+onGenerateRouteコールバック内で受け取り遷移先ウィジェットに渡す方法。

 

(1)遷移元からページ遷移するコード

=>(A)も(B)も全く同じ。

Navigator.pushNamed

メソッドを使う。

Navigator.pushNamed(
  context,
  ExtractArgumentsScreen.routeName,
  arguments: ScreenArguments(
    'Extract Arguments Screen',
    'This message is extracted in the build method.',
  ),
);

(2)ルートテーブルの指定方法

=>(A) : MaterialAppのroutesプロパティで指定する。(受け取るのは遷移先ウィジェット内)

return MaterialApp(
    //...
    routes: {
      ExtractArgumentsScreen.routeName: (context) =>
          ExtractArgumentsScreen(),
    });
);

 

=>(B) : MaterialAppのonGenerateRouteプロパティで指定する。

  return MaterialApp(
      onGenerateRoute: (settings) {
        if (settings.name == PassArgumentsScreen.routeName) {
          final ScreenArguments args = settings.arguments;

          return MaterialPageRoute(
            builder: (context) {
              return PassArgumentsScreen(
                title: args.title,
                message: args.message,
              );
            },
          );
        }
       //...

まずroutesプロパティのテーブルからルート名を探して、見つからない場合onGenerateRouteコールバックが呼び出される模様。


(3)遷移先での受け取り方法

=>(A) : 遷移先のウィジェット内でModalRoute.of(context).settings.argumetnsで受け取って使う。

@override
Widget build(BuildContext context) {

  final ScreenArguments args = ModalRoute.of(context).settings.arguments;
  //...

 

=>(B) : 遷移先ウィジェット生成のコンストラクタのパラメータで渡して遷移先ウィジェット内で使う。

class PassArgumentsScreen extends StatelessWidget {
  static const routeName = '/passArguments';

  final String title;
  final String message;
//↓コンストラクタで受け取って各フィールドにセットする。
  const PassArgumentsScreen({
    Key key,
    @required this.title,
    @required this.message,
  }) : super(key: key);

 




Pass arguments to a named route

Navigatorは共通の識別子を使用して、アプリケーションの任意の部分から名前付きのルートに移動する能力を提供します。

場合によっては、名前付きルートに引数を渡す必要がある場合もあります。たとえば、/userルートに移動した時、ユーザーに関する情報をそのルートに渡したい場合があります。

このタスクは、Navigator.pushNamed()メソッドのargumentsパラメーターを使用して実行できます 。

MaterialAppまたはCupertinoApp コンストラクターに提供されるonGenerateRoute()関数内で引数を抜き出します 

このレシピは、名前付きルートに引数を渡し、ModalRoute.of() とonGenerateRoute()を使用して引数を読み取る方法を示します

次の手順を使用して:

  1. 渡す必要のある引数を定義します。
  2. 引数を抜き出すウィジェットを作成します。
  3. ウィジェットをroutesテーブルに登録します。
  4. 遷移先へページ遷移します。

1. Define the arguments you need to pass

まず、新しいrouteに渡す引数(arguments)を定義します。このサンプルでは、二つのデータ:スクリーンのtitleと、messageを渡します。

二つのデータを渡すために、この情報を格納するクラスを作成します。

//画面間で渡す引数は、どのようなオブジェクトでも渡せます。
//このサンプルではカスタマイズ可能なtitleとmessageを格納する
//クラスを定義します。
class ScreenArguments {
  final String title;
  final String message;

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

 


2. Create a widget that extracts the arguments

遷移先ページであり、遷移元から受け取ったScreenArgumentsインスタンス(オブジェクト)からtitleとmessageを表示するウイジェット

ExtractArgumentsScreenクラス

を定義します。

遷移元から受け取ったScreenArgumentsにアクセスするには、ModalRoute.of()メソッドを使います。

このメソッドは、引数(遷移元から受け取るScreenArgumentsインスタンス)を含む現在のルートを返します。

// ModalRouteから必要なargumentsを抜き出す遷移先ウィジェット
class ExtractArgumentsScreen extends StatelessWidget {
  static const routeName = '/extractArguments';

  @override
  Widget build(BuildContext context) {
    // Extract the arguments from the current ModalRoute settings and cast
    // them as ScreenArguments.
    //現在のModalRouteのsettingsからargumentsを抜き出し、
    //ScreenArguments型にキャストします。
    final ScreenArguments args = ModalRoute.of(context).settings.arguments;

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

 


3. Register the widget in the routes table

次に、MaterialAppウィジェットのroutesプロパティに

Map<String, Widget Function(BuildContext)>型

のテーブルを設定します。

routesプロパティは、「このルート名(文字列)が指定された時は、このウィジェットを生成してそのページに遷移する」という組み合わせを指定するものです。

MaterialApp(
  routes: {
    ExtractArgumentsScreen.routeName: (context) => ExtractArgumentsScreen(),
  },
);

↑のroutesプロパティではルート名

ExtractArgumentsScreen.routeName (‘/extractArguments’)

が指定された時は、

ExtractArgumentsScreen()

ウィジェットを生成してそのページに遷移しましょう、という指定。


4. Navigate to the widget

最後に、ユーザーがボタンをタップした時に、Navigator.pushNamed()メソッドを呼び出して、ExtractArgumentsScreen にページ遷移します。

Navigator.pushNamed()メソッドのargumentsプロパティに、ページ遷移時に受け渡したいオブジェクト(今回はScreenArgumentsインスタンス)を渡します。

そして遷移先のExtractArgumentsScreenにおいて、(ModalRouteを使って)引数(arguments)を抜き出し(受け取り)ます。

// A button that navigates to a named route. The named route
// extracts the arguments by itself.
//名前付きルートに遷移するためのボタン。遷移先ページで
//argumentsを抜き出す。

ElevatedButton(
  child: Text("Navigate to screen that extracts arguments"),
  onPressed: () {
    // When the user taps the button, navigate to a named route
    // and provide the arguments as an optional parameter.
    //ユーザーがボタンをタップした時、名前付きルートに遷移し、
/   //オプショナルパラメータとしてargumentsを遷移先に受け渡す。
    Navigator.pushNamed(
      context,
      ExtractArgumentsScreen.routeName,
      arguments: ScreenArguments(
        'Extract Arguments Screen',
        'This message is extracted in the build method.',
      ),
    );
  },
),

 


Alternatively, extract the arguments using onGenerateRoute

ウィジェット内で直接引数を抽出する代わりに、onGenerateRoute() 関数内で引数を抜き出してウィジェットに渡すこともできます。

onGenerateRouteプロパティに設定されたコールバックは、引数として受け取ったRouteSettengsを基に正しいrouteを生成します。

MaterialApp(
  // Provide a function to handle named routes. Use this function to
  // identify the named route being pushed, and create the correct
  // screen.
  onGenerateRoute: (settings) {
    // If you push the PassArguments route
    if (settings.name == PassArgumentsScreen.routeName) {
      // Cast the arguments to the correct type: ScreenArguments.
      final ScreenArguments args = settings.arguments;

      // Then, extract the required data from the arguments and
      // pass the data to the correct screen.
      return MaterialPageRoute(
        builder: (context) {
          return PassArgumentsScreen(
            title: args.title,
            message: args.message,
          );
        },
      );
    }
  },
);

Interactive example

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        //(2-B)ルートテーブル指定方法
        onGenerateRoute: (settings) {

          if (settings.name == PassArgumentsScreen.routeName) {
            // Cast the arguments to the correct type: ScreenArguments.
            final ScreenArguments args = settings.arguments;
            //(3-B)↓argumentsの受け取り方法
            return MaterialPageRoute(
              builder: (context) {
                return PassArgumentsScreen(
                  title: args.title,
                  message: args.message,
                );
              },
            );
          }
          // The code only supports PassArgumentsScreen.routeName right now.
          // Other values need to be implemented if we add them. The assertion
          // here will help remind us of that higher up in the call stack, since
          // this assertion would otherwise fire somewhere in the framework.
          assert(false, 'Need to implement ${settings.name}');
          return null;
        },
        title: 'Navigation with Arguments',
        home: HomeScreen(),
        //(2-A)ルートテーブル指定方法
        routes: {
          ExtractArgumentsScreen.routeName: (context) =>
              ExtractArgumentsScreen(),
        });
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            // A button that navigates to a named route that. The named route
            // extracts the arguments by itself.
            ElevatedButton(
              child: Text("Navigate to screen that extracts arguments"),
              onPressed: () {
                //↓(1-A)ページ遷移コード
                Navigator.pushNamed(
                  context,
                  ExtractArgumentsScreen.routeName,
                  arguments: ScreenArguments(
                    'Extract Arguments Screen',
                    'This message is extracted in the build method.',
                  ),
                );
              },
            ),

            ElevatedButton(
              child: Text("Navigate to a named that accepts arguments"),
              onPressed: () {
                //↓(1-B)ページ遷移コード
                Navigator.pushNamed(
                  context,
                  PassArgumentsScreen.routeName,
                  arguments: ScreenArguments(
                    'Accept Arguments Screen',
                    'This message is extracted in the onGenerateRoute function.',
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}


class ExtractArgumentsScreen extends StatelessWidget {
  static const routeName = '/extractArguments';

  @override
  Widget build(BuildContext context) {
    //↓(3-A)argumntsの受け取り方法
    final ScreenArguments args = ModalRoute.of(context).settings.arguments;

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

class PassArgumentsScreen extends StatelessWidget {
  static const routeName = '/passArguments';

  final String title;
  final String message;

  const PassArgumentsScreen({
    Key key,
    @required this.title,
    @required this.message,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Text(message),
      ),
    );
  }
}

class ScreenArguments {
  final String title;
  final String message;

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

 

参考

https://flutter.dev/docs/cookbook/navigation/navigate-with-arguments

コメントを残す

メールアドレスが公開されることはありません。