flutter ルーティング#
** ルーティング (Route)** は WEB 開発のシングルページアプリケーションで非常に一般的で、Flutter にも独自のルーティングがありますが、Android システムでは Route は Activity を指し、IOS システムでは View Controller を指します。
ルーティング管理はルーティングスタックを使用して push と pop の操作を行い、ルートをプッシュおよびポップします。スタックに入れることは新しいページを開くことを意味し、スタックから出ることはページを閉じることを意味します。ルーティングスタックを使用するだけでなく、ルーティングのインターセプトやルーティングのリダイレクトなど、他の操作も必要です。
通常のルーティングとルーティングの遷移#
- MyText という新しいルートを作成します(パラメータの受け渡しが可能)。
class MyText extends StatefulWidget {
//他のページからFormページに遷移して名前付きルートで値を渡す
final Map arguments;
const MyText({super.key, required this.arguments});
@override
State<MyText> createState() => _MyTextState();
}
class _MyTextState extends State<MyText> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Route"),
),
body: Center(
child: Text(widget.arguments.toString()),
),
);
}
}
- 他の任意のウィジェットでこのルートを使用します(事前に import が必要です)。ここでは ElevatedButton を使用してデモを行い、ボタンをクリックすると新しいルートに遷移します(パラメータも渡します)。
//imported
ElevatedButton(
onPressed: () {
//ルーティング
//またはNavigator.push、コンポーネントの状況に応じて
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return const MyText(
arguments: {'kano': "kanokano.cn"},
);
},
),
);
},
child: const Text("検索(ルーティング遷移)"),
),
名前付きルートの作成#
注意:名前付きルートは新しい Flutter ドキュメントで使用が推奨されていません
名前付きルートはディープリンクを処理できますが、動作は常に同じでカスタマイズできません。プラットフォームが新しいディープリンクを受信すると、Flutter はユーザーが現在いる場所に関係なく Navigator に新しいルートをプッシュします。
Flutter は名前付きルートを使用するアプリケーションに対してブラウザの進むボタンもサポートしていません。これらの理由から、ほとんどのアプリケーションで名前付きルートの使用を推奨しません。
-
MyText という新しいルートを作成します(ここでは上記の MyText をそのまま使用します)。
-
main.dart で Tabs ルートを使用します。
import 'package:flutter/material.dart';
//通常のコンポーネント
import './mytext.dart';
void main(List<String> args) {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: "Test",
theme: ThemeData(
primarySwatch: Colors.red,
),
//1.ルートを初期化
initialRoute: '/text1',
//直接名前付きルート
routes: {
'/text1': (context) => const MyText(),
},
);
}
}
- ルーティングの遷移
ElevatedButton(
onPressed: () {
//ルーティング
Navigator.pushNamed(context, '/text1');
},
child: const Text("基本ルーティング遷移text1"),
),
名前付きルートでのパラメータの受け渡し#
全体的にはこの 3 ステップです:
- ルートを設定
- ルートを初期化
- onGenerateRouter を設定
class MyApp extends StatelessWidget {
//ルートのパラメータ渡し - 1.ルートを設定(routes.dartとして単独で抽出可能)
Map routes = {
"/": (context) => const Tabs(),
"/news": (context) => const NewsPage(),
"/search": (context) => const NewsPage(),
//パラメータ付き
"/form": (context, {arguments}) {
return FormPage(
arguments: arguments,
);
},
"/shop": (context, {arguments}) {
return ShopPage(arguments: arguments);
}
};
MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: "Test",
theme: ThemeData(
primarySwatch: Colors.red,
),
//2.ルートを初期化
initialRoute: '/',
//ルートのパラメータ渡し-3.ルートを処理(routes.dartとして単独で抽出可能)
//onGenerateRouterを設定(これはインターセプターだと思います)
onGenerateRoute: (RouteSettings settings) {
print(settings); //ルートのパラメータ情報
print(settings.arguments); //渡されたパラメータ
print(settings.name); //ルート名
final String? name = settings.name;
final Function? pageCoutentBuilder = routes[name];
if (pageCoutentBuilder != null) {
//パラメータありの場合
if (settings.arguments != null) {
final Route route = MaterialPageRoute(
builder: (context) =>
pageCoutentBuilder(context, arguments: settings.arguments),
);
return route;
} else {
//パラメータなしの場合
final Route route = MaterialPageRoute(
builder: (context) => pageCoutentBuilder(context),
);
return route;
}
}
return null;
},
);
}
}
- ルーティングの遷移にパラメータを付けて渡す
ElevatedButton(
onPressed: () {
//ルーティング
Navigator.pushNamed(context, '/form',arguments: {"kano": "kanokano"});
},
child: const Text("名前付きルートでのパラメータ渡しform"),
),
上のルートに戻る#
単に次のように使用します。
Navigator.pop(context);
//または
Navigator.of(context).pop()
ルートの置き換え#
一歩一歩戻りたくない場合は、ルートの置き換えモードを使用できます(ページを遷移し、現在のページを破棄します)。
Navigator.of(context).pushReplacementNamed('/xxx')
//または
Navigator.pushReplacementNamed(context,'/xxx')
ルーティングの遷移スタイルの設定#
Material コンポーネントライブラリには、プラットフォームスタイルに一致するルーティング切り替えアニメーションを使用できる
MaterialPageRoute
コンポーネントが提供されています。iOS では左右にスライドして切り替え、Android では上下にスライドして切り替えます。CupertinoPageRoute
は Cupertino コンポーネントライブラリが提供する iOS スタイルのルーティング切り替えコンポーネントで、Android でも左右に切り替えスタイルを使用したい場合はCupertinoPageRoute
を使用できます。
- インポート
import 'package:flutter/cupertino.dart';
MaterialPageRoute
をCupertinoPageRoute
に変更
// import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_application_1/pages/form.dart';
import 'package:flutter_application_1/pages/news.dart';
import 'package:flutter_application_1/pages/tabs/shop.dart';
import '../pages/tabs.dart';
//ルートのパラメータ渡し - 1.ルートを設定(routes.dartとして単独で抽出可能)
Map routes = {
"/": (context) => const Tabs(),
"/news": (context) => const NewsPage(),
"/search": (context) => const NewsPage(),
//パラメータ付き
"/form": (context, {arguments}) {
return FormPage(
arguments: arguments,
);
},
"/shop": (context, {arguments}) {
return ShopPage(arguments: arguments);
}
};
var onGenerateRoute = (RouteSettings settings) {
final String? name = settings.name;
final Function? pageCoutentBuilder = routes[name];
if (pageCoutentBuilder != null) {
//パラメータあり
if (settings.arguments != null) {
final Route route = CupertinoPageRoute(
builder: (context) =>
pageCoutentBuilder(context, arguments: settings.arguments),
);
return route;
} else {
//パラメータなし
final Route route = CupertinoPageRoute(
builder: (context) => pageCoutentBuilder(context),
);
return route;
}
}
return null;
};