Open6
MaterialAppの画面遷移周りのパラメーター
MaterialAppは以下の順序で画面遷移のルートを検索します。
-
/
(初期ルート)の場合:-
home
プロパティが設定されていればそれを使用
-
-
その他のルートの場合:
- まず
routes
テーブルで定義されたルートを検索 - 見つからない場合は
onGenerateRoute
を呼び出し - それでも見つからない場合は
onUnknownRoute
を呼び出し
- まず
具体的な実装例を2つ紹介します:
- シンプルなホーム画面のみの場合:
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
),
)
- 複数画面を持つ場合:
MaterialApp(
routes: <String, WidgetBuilder>{
'/': (BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home Route'),
),
);
},
'/about': (BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('About Route'),
),
);
}
},
)
画面遷移に関する重要なプロパティ:
-
navigatorKey
: Navigatorを制御するためのグローバルキー -
initialRoute
: 初期表示するルート名 -
onGenerateRoute
: 動的なルート生成用のコールバック -
onUnknownRoute
: 未定義のルートが要求された場合のフォールバック -
navigatorObservers
: 画面遷移を監視するためのオブザーバーリスト
これらのプロパティを適切に組み合わせることで、アプリケーションの画面遷移を柔軟に制御できます。
以下に詳細を深堀りしていく。
navigatorKey
- 直接操作の実現
- BuildContext経由でNavigator.of()を使わなくても、NavigatorStateに直接アクセスできます
- 例:
navigatorKey.currentState?.push(...)
のように使えます
- 使用例と利点
final navigatorKey = GlobalKey<NavigatorState>();
MaterialApp(
navigatorKey: navigatorKey,
// ...
)
// どこからでもNavigatorにアクセス可能
navigatorKey.currentState?.push(...);
- 注意点
- navigatorKeyを変更すると、新しいNavigatorが作成されます
- その結果、アプリの状態(ナビゲーション履歴など)が失われます
- navigatorObserversも併せて変更する必要があります
- 制約事項
- onGenerateRouteがnullの場合、navigatorKeyもnullでなければなりません
- これは、Navigatorが構築されない場合、キーも不要だからです
navigatorObservers
NavigatorObserver は Flutter のナビゲーション(画面遷移)を監視/観察するためのクラスです。
主な用途は:
- 画面遷移の監視
- ページがプッシュされた時
- ページがポップされた時
- ルート変更時
これらの遷移イベントをキャッチできます
簡単な例を示します:
class MyNavigatorObserver extends NavigatorObserver {
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
// 新しい画面がプッシュされた時
print('新しいページへ遷移: ${route.settings.name}');
}
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
// 画面がポップされた時
print('前のページに戻る: ${previousRoute?.settings.name}');
}
}
// 使用例:
MaterialApp(
navigatorObservers: [MyNavigatorObserver()],
// ...
)
主な使用ケース:
- アナリティクス追跡
- 画面遷移を記録して分析
- デバッグ
- 開発時に画面遷移を追跡
- カスタム遷移アニメーション
- 遷移時の特別な効果の実装
注意点:
- navigatorKey が変更された場合は、新しいオブザーバーのリストを作り直す必要があります
- routes が設定されていない場合は、navigatorObservers は空リストである必要があります
onGenerateInitialRoutes とは?
onGenerateInitialRoutes
は、アプリ起動時の最初の画面(ルート)を設定するためのコールバックです。複数の画面を同時に設定できる特徴があり、柔軟な初期画面設定が可能です。
基本的な使い方
MaterialApp(
initialRoute: '/home',
onGenerateInitialRoutes: (String initialRoute) {
return [
MaterialPageRoute(builder: (context) => HomeScreen()),
MaterialPageRoute(builder: (context) => WelcomeScreen()),
];
},
)
ユースケース
1. 通常のアプリ起動
MaterialApp(
initialRoute: '/home',
onGenerateInitialRoutes: (initialRoute) => [
MaterialPageRoute(builder: (context) => HomeScreen()),
],
)
2. チュートリアル付きの起動
MaterialApp(
initialRoute: '/tutorial',
onGenerateInitialRoutes: (initialRoute) => [
MaterialPageRoute(builder: (context) => HomeScreen()),
MaterialPageRoute(builder: (context) => TutorialScreen()),
],
)
3. ディープリンク対応
MaterialApp(
initialRoute: '/products/123',
onGenerateInitialRoutes: (initialRoute) {
final productId = initialRoute.split('/').last;
return [
MaterialPageRoute(builder: (context) => HomeScreen()),
MaterialPageRoute(builder: (context) => ProductListScreen()),
MaterialPageRoute(builder: (context) => ProductDetailScreen(id: productId)),
];
},
)
メリット
- 複数画面の同時設定が可能
- ディープリンクの実装が簡単
- 柔軟な初期画面制御
注意点
-
initialRoute
が設定されている場合のみ動作 - アプリ起動時の1回のみ呼び出される
- 設定しない場合は
Navigator.defaultGenerateInitialRoutes
が使用される
まとめ
- 複雑な初期画面遷移が必要な場合
- ディープリンク対応が必要な場合
- チュートリアルなど、複数画面のスタックが必要な場合
適切に活用することで、よりユーザーフレンドリーなアプリ開発が可能になります。
onGenerateRouteとは
onGenerateRoute
は、名前付きルートが要求されたときに呼び出されるコールバック関数です。routes
プロパティで定義されていないルートが要求された場合に使用されます。
基本的な実装例を見てみましょう:
MaterialApp(
onGenerateRoute: (settings) {
// ルート名を取得
final name = settings.name;
// 渡されたパラメータを取得
final args = settings.arguments;
// ルートの生成処理
switch (name) {
case '/detail':
return MaterialPageRoute(
builder: (context) => DetailPage(id: args as String),
);
default:
return null;
}
},
)
実践的な使用例
1. パラメータを含むルーティング
商品詳細ページへの遷移を例に考えてみましょう:
// 商品詳細ページ
class ProductDetailPage extends StatelessWidget {
final String productId;
const ProductDetailPage({required this.productId});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('商品詳細')),
body: Text('商品ID: $productId'),
);
}
}
// ルーティングの設定
MaterialApp(
onGenerateRoute: (settings) {
if (settings.name?.startsWith('/product/') ?? false) {
final productId = settings.name!.split('/').last;
return MaterialPageRoute(
builder: (context) => ProductDetailPage(productId: productId),
);
}
return null;
},
)
2. 遷移アニメーションのカスタマイズ
カスタムトランジションを適用する例:
class FadePageRoute<T> extends PageRoute<T> {
final Widget child;
FadePageRoute({required this.child});
Color get barrierColor => Colors.transparent;
String? get barrierLabel => null;
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return FadeTransition(
opacity: animation,
child: child,
);
}
bool get maintainState => true;
Duration get transitionDuration => Duration(milliseconds: 300);
}
// 使用例
MaterialApp(
onGenerateRoute: (settings) {
switch (settings.name) {
case '/smooth-transition':
return FadePageRoute(
child: SmoothTransitionPage(),
);
}
return null;
},
)
注意点
-
onGenerateRoute
がnull
を返す場合、アプリケーションはNavigator.defaultRouteName
('/')にフォールバックします。 -
通常の運用では、
onGenerateRoute
はnull
を返すべきではありません。
onUnknownRouteとは
onUnknownRoute
は、Flutterアプリケーションで存在しないルートにアクセスしようとした際のフォールバックハンドラーとして機能する重要なプロパティです。
基本構文
MaterialApp(
onUnknownRoute: (RouteSettings settings) {
return MaterialPageRoute(
builder: (BuildContext context) {
return const NotFoundPage();
},
);
},
);
呼び出されるタイミング
onUnknownRoute
は以下の場合に呼び出されます:
-
onGenerateRoute
がルートの生成に失敗した場合 - 指定されたルートが
routes
マップに存在しない場合
一般的なユースケース
1. エラーログの記録
onUnknownRoute: (RouteSettings settings) {
// エラーログの記録
debugPrint('未知のルートへのアクセス: ${settings.name}');
return MaterialPageRoute(
builder: (context) => const NotFoundPage(),
);
},
2. アナリティクス連携
onUnknownRoute: (RouteSettings settings) {
// アナリティクスイベントの送信
analytics.logEvent(
name: 'unknown_route_access',
parameters: {'route': settings.name},
);
return MaterialPageRoute(
builder: (context) => const NotFoundPage(),
);
},
注意点
-
onUnknownRoute
は最後の手段として使用されます - 初期ルート(
initialRoute
)には適用されません - アプリ内のエラーや外部(Androidインテントなど)からのルートリクエストで発生する可能性があります