モバイルアプリの最も基本的な側面の1つは、ユーザーが異なるページ間を移動できるようにすることです。 幸いなことに、Flutterを使用すると、特に多くのフロントエンドソリューションと比較した場合に、ルートの作成や画面間の移動が非常に簡単になります。

プロジェクトファイルの設定

この例では、main.dartファイルの4つの画面があり、ナビゲーションバーを独自のファイルに分割します。

* screens 📂
  * account_screen.dart
  * balance_screen.dart
  * transfer_screen.dart
  * welcome_screen.dart
* main.dart
* navbar.dart

ルートの命名

ほとんどの場合、各ルートを独自のファイルに分割する必要がありますが、ここではそれらをmain.dartに配置します。

MaterialAppでは、キーと値のペアのリストであるroutesマップを設定できます。 このマップの各アイテムは、文字列値を、レンダリングするページを返すコールバック関数にリンクします。 これのポイントは、完全な(context) => WelcomeScreen()ではなく、新しいページが必要なときはいつでも'welcome_screen'のようなものを投げることによって開発をスピードアップすることです。

ホームページを設定するには、MaterialApphomeプロパティまたはinitialRouteプロパティのいずれかを使用できます。 それらは事実上同じことをしますが、homeWelcomeScreen()のようにクラス自体を取り、initialRouteroutesマップからキーを取ります。 コンパイラが混乱するため、両方を使用することはできません。

main.dart
import 'package:flutter/material.dart';
import './screens/welcome_screen.dart';
import './screens/account_screen.dart';
import './screens/balance_screen.dart';
import './screens/transfer_screen.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Navigation Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  
  Widget build(BuildContext context) {
    return MaterialApp(
       home: WelcomeScreen(), 
       routes: {
        'welcome_screen': (context) => WelcomeScreen(),
        'account_screen': (context) => AccountScreen(),
        'balance_screen': (context) => BalanceScreen(),
        'transfer_screen': (context) => TransferScreen()
    });
  }
}

これは問題なく機能しますが、これらの各ルートを頻繁に入力することになり、文字列を使用するだけでは、わずかなタイプミスをしたときにデバッグが困難になる可能性があります。 代わりに、各クラスの静的ID変数に各キーを格納し、そのIDにアクセスするだけで、コードの脆弱性が少し低くなります。 これにより、VSCodeのIntelliSenseのメリットも得られ、ページが利用できない理由を理解するのに役立ちます。

この例の各画面は、idとテキストウィジェットを除いて同じです。 また、後で作成するウィジェットに下部のナビゲーションバーを設定しています。

welcome_screen.dart
import 'package:flutter/material.dart';
import '../navbar.dart';

class WelcomeScreen extends StatelessWidget {
  static const String id = 'welcome_screen';

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        bottomNavigationBar: Navbar(),
        child: Text('Welcome'),
      ),
    );
  }
}

これで、文字列を各画面のIDに置き換えることができます。 クラス自体を実際に呼び出さずにアクセスしていることに注意してください。

main.dart
class _MyHomePageState extends State<MyHomePage> {
  
  Widget build(BuildContext context) {
    return MaterialApp(initialRoute: WelcomeScreen.id, routes: {
      WelcomeScreen.id: (context) => WelcomeScreen(),
      AccountScreen.id: (context) => AccountScreen(),
      BalanceScreen.id: (context) => BalanceScreen(),
      TransferScreen.id: (context) => TransferScreen()
    });
  }
}

プッシュアンドポップ

フロントエンドのWeb開発とは異なり、モバイルルーティングは、画面を「積み重ねる」ことに基づいています。 ウェルカム画面からアカウント画面に移動するとき、実際にはページを変更するのではなく、アカウント画面をスタックに追加して、前のページをカバーします。 ウェルカム画面に戻るには、最上層を破棄するか、popオフにして、その下に既にレンダリングされているページを表示する必要があります。

これを行うためのNavigatorにはかなりの数の異なる方法があり、ここで完全に調べることができます。 必要な主な2つは、スタックに追加するpushNamedと、最新のレイヤーを削除するpopです。 popには、ビルドのcontextメソッドとpushメソッドに、contextとルートに設定したページのキーが必要です。

Namedが追加されたメソッドは、MaterialAppでルートを設定した場合に使用されます。それ以外の場合は、キーの代わりにコールバック自体を渡すことができます。

navbar.dart
import 'package:flutter/material.dart';
import './screens/account_screen.dart';
import './screens/balance_screen.dart';
import './screens/transfer_screen.dart';

class Navbar extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          FlatButton(
              onPressed: () => Navigator.pop(context),
              child: Icon(Icons.arrow_left, color: Colors.white, size: 40)),
          FlatButton(
              onPressed: () => Navigator.pushNamed(context, BalanceScreen.id),
              child: Icon(Icons.account_balance, color: Colors.white)),
          FlatButton(
              onPressed: () => Navigator.pushNamed(context, TransferScreen.id),
              child: Icon(Icons.sync, color: Colors.white)),
          FlatButton(
              onPressed: () => Navigator.pushNamed(context, AccountScreen.id),
              child: Icon(Icons.account_circle, color: Colors.white)),
        ],
      ),
    );
  }
}

Flutter Navigation demo

結論

ルーティングとナビゲーションに関しても、Flutterは効率と使いやすさで非常に優れています。 この短いチュートリアルが、この新しいテクノロジーを理解するのに役立つことを願っています。