🍎 FlutterでbottomNavigationBarを固定して画面遷移する
この記事は最終更新日から4年以上経過しています。
ちょっと作りたいアプリができたので、Flutter を触っています。
以前お仕事で触った時には表題の件にとても苦労したのですが、今だと最適解に見える例がいくつがアップされていました。ありがたや…
- Flutter で BottomNavigatorBar を残したまま各画面を遷移させる
- Flutter Case Study: Multiple Navigators with BottomNavigationBar
- Flutter の Bottom Navigation による画面遷移について
ほぼほぼ似た感じのコードを使わせていただいたのですが、以下の改良を加えてみました。
- タブ内だけでなくタブの外(一つ上の階層)にも画面を開けるように
- 上記理由で GlobalKey を複数使うので、Singleton に纏めておいて必要な時にそこから適宜呼び出すように
- Routing や TabItem の設定を別ファイルで作成し、なるべく他のアプリ作る時にも使いまわせるような構造に
- ページ遷移の時に次の画面に引数を渡せるように
ポイントとしては root と tab で使用している GlobalKey をそれぞれ Singlton に格納しておいて、そこから呼び出すようにしたり、
コピーしました
class NavigationService {
//singleton
static final _instance = NavigationService._internal();
NavigationService._internal();
static NavigationService getInstance() {
return _instance;
}
//root state
GlobalKey<NavigatorState> rootNavigatorKey = GlobalKey<NavigatorState>();
//tab state
TabItem currentTab = TabItem.home;
Map<TabItem, GlobalKey<NavigatorState>> tabNavigatorKeys = {
TabItem.home: GlobalKey<NavigatorState>(),
TabItem.star: GlobalKey<NavigatorState>(),
TabItem.settings: GlobalKey<NavigatorState>(),
};
static NavigatorState getRootState() {
return NavigationService.getInstance().rootNavigatorKey.currentState;
}
static NavigatorState getCurrentTabState() {
return NavigationService.getInstance()
.tabNavigatorKeys[NavigationService.getInstance().currentTab]
.currentState;
}
static Future<dynamic> pushInTab(String routeName, {Object arguments}) {
return Navigator.push(
NavigationService.getCurrentTabState().context,
Routes.onGenerateRoute(
RouteSettings().copyWith(name: routeName, arguments: arguments),
),
);
}
...
}
あとは引数として渡す値の中に fullscreenDialog
を入れておいて、同じページでも onGenerateRoute
の時にそれを参照して渡すようにしたり(これで同じページをタブ内でも外でも使えるようになります。実際使うかわからないですが…)
コピーしました
class ScreenArguments {
final String message;
final bool fullscreenDialog;
ScreenArguments(this.message, {this.fullscreenDialog = false});
}
コピーしました
return MaterialPageRoute(
builder: (context) => DammyPage(
title: 'page name',
arguments: settings.arguments,
),
fullscreenDialog: settings.arguments.fullscreenDialog,
);
チーム仕事の時にはあんまりこんな書き方をしなさそうですが、個人プロジェクトなので自分個人の使いやすさ的なところに焦点を当てて試行錯誤しています。他にもちょこちょこ触っているのですが未来の自分用メモみたいなものなので、あとは GitHub のリンクを貼っておきます。
よく見られている記事