画面遷移
Rivorpod を使用する例。
拡張性を求められるアプリ開発にChangeNotifierProviderは勧められない、とのこと(公式)。
StateNotifyを使用するようにした。
◎画面遷移用のGlobal変数 を宣言
// 画面遷移用
final gNavigatorKey = GlobalKey<NavigatorState>();
final gPageControlProvider = StateNotifierProvider(
(ref) => PageNotifier(),
);
◎PageControlクラスを作成
・PageNotifier を継承して、PageControlクラスを作成する(要検討)
・enum Pagesで、何のページか判別し易くした。
// 画面遷移用
enum Pages{
TopDummyPage,
MainListPage,
InputPage,
ConfigurePage,
TableViewPage,
IntroductionPage,
}
enum Pages{
TopDummyPage,
MyHomePage,
SettingPage,
}
class PageNotifier extends StateNotifier<Pages>{
PageNotifier() : super (Pages.MyHomePage);
Pages get page => state;
void ChangePage(Pages inPage){
state = inPage;
}
}
◎ RouterDelegate を記載。
・main.dartに追記するとわかりやすいのでは。
・class Empty {}は、setNewRoutePath(Empty configuration) async {}に使用するので必須。
(一部抜粋)
class Empty {}
// 画面遷移 RouterDelegate
class AppRouterDelegate extends RouterDelegate<Empty>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<Empty> {
AppRouterDelegate(this.ref);
final WidgetRef ref;
@override
final GlobalKey<NavigatorState>? navigatorKey = gNavigatorKey;
@override
Widget build(BuildContext context) {
var _pageProvider = ref.watch(gPageControlProvider);
return Navigator(
key: navigatorKey,
pages: [
// ここにページを置く
// サブページを重ねる場合はページの並べ方を工夫すること
const MaterialPage(child: TopDummyPage()), // rootのダミーページ
// 以下、サブページ。ページを増やすときはここに追加する
if (ref.read(gPageControlProvider.notifier).page == Pages.MyHomePage) const MaterialPage(child: MyHomePage()) ,
if (ref.read(gPageControlProvider.notifier).page == Pages.SettingPage) const MaterialPage(child: SettingPage()),
//サブページを重ねる場合の例
//if (_pageProvider.page == Pages.SettingPageSub) const MaterialPage(child: SettingPage()),
//if (_pageProvider.page == Pages.SettingPageSub) const MaterialPage(child: SettingPageSub()),
],
onPopPage: (route, result) {
if(route.didPop(result) == false) return false; // 失敗
// 成功時
// 戻るボタンを押したとき、強制的に最初の画面へ
// サブページを重ねる場合は、一工夫必要。
ref.read(gPageControlProvider.notifier).ChangePage(Pages.MyHomePage);
return true;
},
);
}
@override
Future<void> setNewRoutePath(Empty configuration) async {}
}
◎ページを記述する
・StatelessWidget でもStatefullWidgetでもConsumerWidgetでもお好みで。
(一部抜粋)
// CircluarProgress を表示するrootのdummyページ
class TopDummyPage extends StatelessWidget {
const TopDummyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context){
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children:[
CircularProgressIndicator(),//
]
),
)
);
}
}
◎MaterialApp 中home:部分を変更する
home:
Router(
routerDelegate: AppRouterDelegate(ref),
),
◎画面遷移する
・利用するウイジェット内で、ref.watch()する。
final _pageProvider = ref.watch(gPageControlProvider);
・watch()したウイジェット内で以下のように使用する
ref.read(gPageControlProvider.notifier).ChangePage(Pages.SettingPage);