【 Flutter 】Flutter を 基礎 から 学習 ( スタートガイド編 ) part22 画面遷移 Named Routes

基礎 から 学ぶ Flutter 」という書籍で  学習 したことを ブログでアウトプットしていこうと思います。今回は スタートガイド編 ( part22 )です。

前回

【 Flutter 】Flutter を 基礎 から 学習 ( スタートガイド編 ) part21 画面遷移 Named Routes

Named Routesの続きになります。

画面遷移

Named Routes

Named Routesの基本実装は以下のようになります。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override

Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',

theme: ThemeData(
          primarySwatch: Colors.blue,

),

// home: MyHomePage(title: 'Flutter Demo Home Page'),

initialRoute: '/',

routes: {
          '/': (context) => FirstPage(),

'/second': (context) => SecondPage(),

});

}
}

class FirstPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('First Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/second');

},

child: Text('Next Page'),

),

),

);

}
}

class SecondPage extends StatelessWidget {
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Secnd Page')),

body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);

},

child: Text('Go back'),

),

),

);

}
}
 

動作は今までの実装と変わりませんね。

 

値の渡し方は2つの方法があります。

  • pushNmaed()の引数argumentsプロパティに設定する
    • このとき、ModalRouteクラスを使用し受け取る
    • 本書ではvar messageFromFirst = ModalRoute.of(context).settings.arguments;と記載されているが、以下のエラーが発生。
      Error: Property 'settings' cannot be accessed on 'ModalRoute<Object?>?' because it is potentially null.
      - 'ModalRoute' is from 'package:flutter/src/widgets/routes.dart' ('/D:/flutter/packages/flutter/lib/src/widgets/routes.dart').
      - 'Object' is from 'dart:core'.
      Try accessing using ?. instead.
      var messageFromFirst = ModalRoute.of(context).settings.arguments;
                                                    ^^^^^^^^/* Your code... */

      var messageFromFirst = ModalRoute.of(context)?.settings.arguments;とした。

    • import 'package:flutter/material.dart';
      
      void main() {
        runApp(MyApp());
      }
      
      class MyApp extends StatelessWidget {
        @override
      
      Widget build(BuildContext context) {
          return MaterialApp(
              title: 'Flutter Demo',
      
      theme: ThemeData(
                primarySwatch: Colors.blue,
      
      ),
      
      // home: MyHomePage(title: 'Flutter Demo Home Page'),
      
      initialRoute: '/',
      
      routes: {
                '/': (context) => FirstPage(),
      
      '/second': (context) => SecondPage(),
      
      });
      
      }
      }
      
      class FirstPage extends StatelessWidget {
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(title: const Text('First Page')),
      
      body: Center(
              child: ElevatedButton(
                onPressed: () {
                  Navigator.pushNamed(context, '/second',
      
      arguments: 'messageFromFirst'); // ★ここです。
      
      },
      
      child: Text('Next Page'),
      
      ),
      
      ),
      
      );
      
      }
      }
      
      class SecondPage extends StatelessWidget {
        Widget build(BuildContext context) {
          var messageFromFirst = ModalRoute.of(context)?.settings.arguments;
      
      print(messageFromFirst);
          return Scaffold(
            appBar: AppBar(title: const Text('Second Page')),
      
      body: Center(
              child: ElevatedButton(
                onPressed: () {
                  Navigator.pop(context);
      
      },
      
      child: Text('Go back'),
      
      ),
      
      ),
      
      );
      
      }
      }
       

      実行してみました。
      ※コンソールに出力する実装なので画面遷移自体は特に変化ありません。

  • routesプロパティと同列に、onGenerateRouteプロパティを定義
    • コンストラクタで渡す方法らしいです。本書ではコンストラクタ定義まで記載がないので流れのまま実装したのでは動作しない。
      ※動的にSecondPageにコンストラクタを定義しているのかと思いましたよ(笑
      「画面間のデータ受け渡し」の説のSecondPageの実装を参考にしましょう。
      さらに、settings.argumentsの戻り値の方はObject?らしいのでSecondPageのコンストラクタで受ける際は注意が必要です。
    • import 'package:flutter/material.dart';
      
      void main() {
        runApp(MyApp());
      }
      
      class MyApp extends StatelessWidget {
        @override
      
      Widget build(BuildContext context) {
          return MaterialApp(
            title: 'Flutter Demo',
      
      theme: ThemeData(
              primarySwatch: Colors.blue,
      
      ),
      
      // home: MyHomePage(title: 'Flutter Demo Home Page'),
      
      initialRoute: '/',
      
      routes: {
              '/': (context) => FirstPage(),
      
      //'/second': (context) => SecondPage(),
      
      },
      
      onGenerateRoute: (settings) {
              if (settings.name == '/second') {
                var messageFromFirst = settings.arguments;
                return MaterialPageRoute(
                  builder: (context) {
                    return SecondPage(messageFromFirst);
      
      },
      
      );
      
      }
              return null;
      
      },
      
      );
      
      }
      }
      
      class FirstPage extends StatelessWidget {
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(title: const Text('First Page')),
      
      body: Center(
              child: ElevatedButton(
                onPressed: () {
                  Navigator.pushNamed(context, '/second',
      
      arguments: 'messageFromFirst');
      
      },
      
      child: Text('Next Page'),
      
      ),
      
      ),
      
      );
      
      }
      }
      
      class SecondPage extends StatelessWidget {
        final Object? messageFromFirst;
      
      SecondPage(this.messageFromFirst);
      
      Widget build(BuildContext context) {
          // var messageFromFirst = ModalRoute.of(context)?.settings.arguments;
      
      print(this.messageFromFirst);
          return Scaffold(
            appBar: AppBar(title: const Text('Second Page')),
      
      body: Center(
              child: ElevatedButton(
                onPressed: () {
                  Navigator.pop(context);
      
      },
      
      child: Text('Go back'),
      
      ),
      
      ),
      
      );
      
      }
      }
       
    • 実行した結果

最後に

ソースコードが断片的なのでなかなか難しいですね😅
今日はここまで!