Routeとは何か、Flutterにおけるルートの種類と作成方法

著者: IT Sectr 公開日: 2026-07-02 読了時間: 8 分

RouteはFlutterの抽象クラスで、Navigatorのナビゲーション履歴内の個別の画面やページを表します。Routeの具体的な実装であるMaterialPageRoute、CupertinoPageRoute、PlatformRouteは、画面の表示方法と遷移時に使用するアニメーションを決定します。通常のウィジェットとは異なり、RouteにはdidPush、didPop、didReplace、didChangeNextというメソッドを持つ独自のライフサイクルがあります。Flutter API Reference (2026)によると、各RouteはModalBarrierを管理し、プラットフォーム固有の機能(iOSのスワイプバック)を考慮し、画面間の状態の分離を保証します。

重要ポイント

  • Route — Flutterの抽象画面クラスで、独自のライフサイクル(didPush、didPop、didReplace、didChangeNext)を持つ
  • MaterialPageRoute — Androidおよびデスクトップ向けのMaterialアニメーション(下からスライド)を備えた標準的なRoute実装
  • CupertinoPageRoute — iPhoneおよびiPad向けのiOSアニメーション(右からスライド+ジェスチャースワイプバック)を備えたRoute実装
  • ライフサイクル — Routeは遷移、アクティブ、非アクティブ、破棄の段階を経る
  • データ転送 — Routeはコンストラクターを介して引数を受け取り、完了時にFutureを介して結果を返す

FlutterにおけるRouteとは

RouteはFlutterのナビゲーションシステムの基盤です。ユーザーがアプリケーションで見る各画面は、Navigatorスタック内にあるRouteオブジェクトで表されます。Routeは制御コードから画面を抽象化します。NavigatorがRouteを追加・削除する一方、Routeの内部にはユーザーが見るインターフェースがあります。このアーキテクチャにより、ナビゲーションと表示の責任が分離されます。

単純なウィジェットの置き換えとは異なり、Routeは通常のウィジェットでは利用できないサービスを提供します:ModalBarrier(ダイアログ表示時の背景の暗転)、出入りのアニメーション制御、Androidのハードウェア戻るボタンの処理、画面間のスムーズな遷移のためのHeroアニメーションとの統合。

Flutter Cookbook (2026)によると、RouteはHeroアニメーションの重要な要素です。あるRouteのHeroウィジェットは、次のRouteのHeroウィジェットへの遷移を自動的にアニメーション化し、要素が“飛ぶ”ような効果を生み出します。これは、Routeがアニメーション中に両方の画面をOverlayに保持するから可能です。

ナビゲーションの構成要素としてのRoute

Routeは、シンプルなモバイルアプリケーション(Navigator 1.0経由)と、ディープリンクを伴う複雑なシナリオ(Navigator 2.0)の両方の基盤です。Navigator 2.0では、RouteはRouterDelegateがルート設定から変換するPageを表します。したがって、選択したアプローチやパッケージに関係なく、Flutterのナビゲーションシステムで作業するにはRouteの理解が不可欠です。

Routeの種類:MaterialPageRouteとCupertinoPageRoute

Flutterは、それぞれ特定のプラットフォームに動作を適応させた、いくつかの組み込みRoute実装を提供します。正しいRouteタイプを選択することはユーザーエクスペリエンスに影響します。AndroidでのMaterialアニメーションとiOSでのCupertinoアニメーションは、“ネイティブ”アプリケーションの感覚を生み出します。

Routeの種類アニメーションプラットフォーム特徴
MaterialPageRoute下から上にスライドAndroid、デスクトップ遷移時の影、自動SafeArea処理
CupertinoPageRoute右から左にスライドiOS、iPadOSジェスチャースワイプバック、遷移時の透明な背景
PlatformRoute自動選択全プラットフォームTargetPlatformに基づいてタイプを選択
PageRouteBuilderカスタム全プラットフォームAnimationControllerによるアニメーションの完全制御

MaterialPageRoute:Androidの標準

MaterialPageRouteは最もよく使われるRoute実装です。新しい画面が下から上に徐々に現れるようにアニメーションします。終了時には、画面は上から下にアニメーションして元の位置に戻ります。ツールバー(AppBar)と画面本体は別々にアニメーションし、階層効果を生み出します。

CupertinoPageRoute:iOSのナビゲーションスタイル

CupertinoPageRouteはiOSのUINavigationControllerを模倣します。新しい画面は右から入り、前の画面を覆います。主な特徴は、CupertinoBackGestureDetectorを介して実装されたインタラクティブなスワイプバックジェスチャーのサポートです。このジェスチャーはアニメーション中でも処理され、iPhoneユーザーにはおなじみの自然な動作を提供します。

Routeのライフサイクル:作成から破棄まで

Routeには、通常のStatefulWidgetのライフサイクルとは異なる独自のライフサイクルがあります。このサイクルを理解することは、適切なデータ初期化、ストリームサブスクリプション、画面終了時のリソース解放に必要です。

Routeライフサイクルの段階

Routeのライフサイクルは4つの主要な段階で構成されます。遷移 — Routeが作成され、入場時にアニメーションします(didPushが呼ばれます)。アクティブ — Routeが完全に表示され、ユーザーと対話します。非アクティブ — 別のRouteが現在のRouteを覆います(ダイアログ、ボトムシート)が、Routeはスタックに残ります。破棄 — Routeがスタックから削除され破棄されます。didPopとdisposeが呼ばれます。

Routeのライフサイクルメソッドはカスタム実装でオーバーライドできます。たとえば、didPopはRouteがスタックから削除されるときに呼ばれます。ここで下書きデータを保存できます。didChangeNextはスタック内の次のRouteが変更されたときに呼ばれます。ナビゲーション履歴が変更されたときにUIを更新するのに便利です。

Flutter API Route.didPop (2026)によると、RouteのライフサイクルとRoute内のStateのライフサイクルを混同しないことが重要です。Route内のStatefulWidgetには独自のinitStateとdisposeがあり、これらはそれぞれ遷移段階と破棄段階で呼び出されます。Routeは内部のStateよりも長く生存します。Routeは、そのウィジェットが別のRouteによって一時的に隠されている場合でも、Overlayに残ります。

Routeを介した画面間のデータ受け渡し

Routeは、入力時(作成時)と出力時(完了時)の両方でデータを受け渡すメカニズムを提供します。Routeを介した適切なデータ受け渡しにより、グローバル変数やInheritedWidgetが不要になり、ナビゲーションが型安全で予測可能になります。

新しい画面にデータを渡すには、受け取り側ウィジェットのコンストラクターまたはNavigator.pushNamedのargumentsパラメーターを使用します。Route内では、RouteSettings.argumentsを介してデータにアクセスできます。これはRouteオブジェクトに格納されます。このアプローチは、MaterialPageRoute、CupertinoPageRoute、カスタム実装など、すべてのRouteタイプで機能します。

データを返すには、Navigator.pop(context, result)の第2引数を使用します。Navigator.pushはFutureを返し、popに渡された値で完了します。popが引数なしで呼ばれた場合、Futureはnullで完了します。このメカニズムはAndroidのstartActivityForResultやiOSのcompletion handlerに類似していますが、Dart Futuresを介して実装されています。

Routeコンストラクターを介したデータ受け渡し

MaterialPageRouteを使ってNavigator.pushを直接呼び出す場合、データはターゲット画面のコンストラクターを介して渡されます。MethodChannelは使用されません。これは純粋なDartの相互作用です。このアプローチは、複雑なオブジェクトの型安全な受け渡しに適しています。

カスタムRoute作成の例

独自のアニメーションとデータ受け渡しを備えたカスタムRouteを作成する例を見てみましょう。PageRouteBuilderを使用すると、アニメーションのカーブと期間を完全に制御して、入退場アニメーションを定義できます。

dart
// スライドアニメーション付きカスタムRoute
Navigator.push(context, PageRouteBuilder(
  pageBuilder: (context, animation, secondaryAnimation) {
    return DetailPage(productId: '42');
  },
  transitionsBuilder: (context, animation, secondaryAnimation, child) {
    const begin = Offset(0.0, 0.3);
    const end = Offset.zero;
    final tween = Tween(begin: begin, end: end);
    final offsetAnimation = animation.drive(tween);
    return SlideTransition(position: offsetAnimation, child: child);
  },
  transitionDuration: const Duration(milliseconds: 400),
));

// 画面からデータを返す
ElevatedButton(
  onPressed: () => Navigator.of(context).pop({'selected': true, 'id': '42'}),
  child: const Text('選択'),
);

// 呼び出し元画面で結果を取得
final result = await Navigator.push(context, MaterialPageRoute(
  builder: (context) => const SelectionPage(),
));
if (result != null) {
  print('選択済み: ${result['selected']}');
}

この例では、PageRouteBuilderが透明度を伴う下からのカスタムスライドアニメーションを定義しています。transitionDurationがアニメーションの速度を設定します。コードは結果の受け渡しも示しています。詳細画面はユーザーの選択を含むMapを返し、呼び出し元画面はpushからのFutureを介してこのデータを受け取ります。Routeは完全な分離を保証します。詳細画面の下書きはリストの状態に影響しません。

よくある質問

FlutterにおけるRouteとWidgetの違いは何ですか?

Routeはナビゲーションレベルで画面を管理するオブジェクトです。アニメーション、ModalBarrier、ライフサイクルを保存します。Widgetはインターフェースの一部の記述です。Routeは内部にWidgetを含みますが、通常のウィジェットでは利用できないサービス(Overlayレイヤー、Heroアニメーション)も提供します。1つのRouteは、任意の深さの複雑なウィジェット階層を含むことができます。

カスタムアニメーションでRouteを作成するには?

pageBuilder(画面構築)とtransitionsBuilder(アニメーション定義)パラメーターを持つPageRouteBuilderを使用します。transitionsBuilderでは、並列アニメーション用にanimation(0.0–1.0)とsecondaryAnimationが利用可能です。完全に制御するには、Routeのサブクラスを作成し、buildPage、createAnimationController、buildTransitionsをオーバーライドして、低レベルのAnimationControllerにアクセスします。

Route間で複雑なオブジェクトを渡すには?

複雑なオブジェクトを渡すには、Navigator.pushを直接呼び出すときにターゲット画面のコンストラクターを使用するか、pushNamedでargumentsパラメーターを使用します。オブジェクトがシリアル化可能(Map、JSON、またはカスタムクラス)であることを確認してください。Flutterで型安全に受け渡しを行うには、freezedやjson_serializableモデルを使用します。これらはRouteSettingsを介した受け渡し時に正しいデシリアライゼーションを保証します。

Routeがdisposeを呼び出さないのはなぜですか?

RouteがNavigatorスタックに残っている場合、Route.disposeは呼び出されません。たとえば、新しいRouteを開くとき、古いRouteは非アクティブ状態になりますが破棄されません。素早く戻るためにスタックに残ります。Disposeは、pop、pushReplacement、またはpushAndRemoveUntilを介してRouteがスタックから削除された場合にのみ呼び出されます。リソースを解放するには、Route自身のdisposeではなく、Route内のStateのdisposeを使用してください。

現在どのRouteがアクティブかを確認するには?

BuildContextから現在のRouteを取得するにはModalRoute.of(context)を使用します。ModalRoute.isActiveプロパティは、Routeが現在表示されている画面かどうかを示します。ModalRoute.isCurrent — Routeがスタックの先頭にある場合はtrue。スタックの変更を監視するには、RouteAwareとRouteObserverを介してNavigatorオブザーバーに購読します。これらはアクティブなRouteの変更を通知します。

まとめ

  • Route — Flutterの抽象画面クラスで、ライフサイクル(didPush、didPop、didReplace、didChangeNext)とModalBarrierおよびHeroアニメーションのサポートを持つ
  • MaterialPageRoute — 下からのスライドアニメーション、影、自動SafeAreaを備えたAndroid実装
  • CupertinoPageRoute — 右からのスライドアニメーションとインタラクティブなスワイプバックジェスチャーを備えたiOS実装
  • PageRouteBuilder — transitionsBuilderとAnimationControllerを介してカスタムアニメーションでRouteを作成するユーティリティ
  • データ受け渡し — 入力時はRouteコンストラクター(push)またはarguments(pushNamed)を介して;出力時はFutureを伴うNavigator.pop(context、result)を介して
  • ライフサイクル — 4つの段階:遷移(didPush)、アクティブ、非アクティブ(別のRouteで覆われる)、破棄(didPop + dispose)
  • 画面の分離 — 各Routeは独自のBuildContextと状態を持ち、リークを防ぎデータ管理を簡素化する

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください