先に実装のせておきます
どなたかの参考になれば幸いです。
こうした方が良いなどあればご教示願います!
custom_roter_delegate.dart
enum PageName {
hogePage,
fugaPage,
fooPage
}
// これをローカルに宣言してしまうと画面遷移アニメーションが表示されないようになってしまいます。
final GlobalKey<NavigatorState> _nestedNavigatorKey = GlobalKey<NavigatorState>();
class CustomRouterDelegate extends RouterDelegate<void>
with ChangeNotifier, PopNavigatorRouterDelegateMixin {
CustomRouterDelegate(this.ref);
final WidgetRef ref;
@override
GlobalKey<NavigatorState>? get navigatorKey => _nestedNavigatorKey;
@override
Widget build(BuildContext context) {
final fooPageTitle = ref.watch(fooPageTitleProvider);
return Navigator(
key: _nestedNavigatorKey,
pages: [
const MaterialPage(
arguments: PageName.hogePage,
child: HogePage(),
),
if (ref.watch(showFugaPageProvider))
MaterialPage(
// nameというプロパティも存在しますが、こちらはルートのnameなのでどの画面かという情報を渡すには適していないと思われます。
arguments: PageName.fugaPage,
child: FugaPage(),
),
if (fooPageTitle.isNotEmpty)
MaterialPage(
arguments: PageName.fooPage,
child: FooPage(title: fooPageTitle),
)
],
onPopPage: (route, result) {
// 戻る先の画面がない場合にはfalse返す
if (!route.didPop(result)) {
return false;
}
// 戻る挙動の元の画面をpagesから除く為に値を戻したりする
final pageName = route.settings.arguments as PageName;
switch (pageName) {
case PageName.fugaPage:
ref.read(showFugaPageProvider.notifier).state = false;
break;
case PageName.fooPage:
ref.read(fooPageTitleProvider.notifier).state = "";
break;
default:
break;
}
return true;
},
);
}
@override
Future<void> setNewRoutePath(void configuration) async {}
}
final showFugaPageProvider =
StateProvider.autoDispose<bool>((ref) => false);
final fooPageTitleProvider = StateProvider<String>((ref) => "");
でこれを使いたいWidgetのところに置いてあげる
使いたいwidget.dart
Container(
child: Router(routerDelegate: CustomRouterDelegate(ref));
)
ざっくり実装を載せましたがこんな感じでいけます。
私がこれを実装するまでに起こった事象
・どこかのサイトを見てnavigatorKeyをCustomRouterDelegateのコンストラクタのところでインスタンス生成してしまっていたため、画面遷移animationが消える
・onPopPageのところでproviderに値を戻す操作をしていなかったため、戻るボタンで戻ってきた後に再度画面遷移しようとしたら反応しなくなってしまう