Flutter Navigator (2.0) 如何在某个 Pop 事件中 return 从 Nested Router 控制到 Base Router?
Flutter Navigator (2.0) How can I return control to the Base Router from a Nested Router on a certain Pop event?
我想使用 Flutter’s (2.0) navigation for routing on my mobile app. I cannot find cookbook examples and followed the recommended guide, implementing the nested router example。
注意===
如果呈现的视图在应用程序中具有唯一的路由 (uri),我将其称为页面。
如果它没有唯一的路线,我称之为屏幕。
========
基本路由器 select 在应用程序的页面之间。 “资源仪表板”中的嵌套路由器使用 resourceViewState 对象 select 屏幕在“资源仪表板”页面中呈现。只需使用如下所示的 selectedIndex,我就可以根据用户在 Material Design Drawer.
中 selected 的索引更改屏幕
因此,当用户在上图中的任何非默认屏幕(即细节 A、细节 B)上,并且有弹出事件时,用户会 returned 到默认屏幕。如果用户从默认屏幕弹出,他们将 returned 到嵌套路由器之外的“Select 资源”页面。但是我还有一个棘手的案例要处理(或者我可能没有很好地处理这些案例:))
@override
Widget build(BuildContext context) {
int selectedIndex = resourceViewState.selectedIndex;
return Navigator(
key: navigatorKey,
pages: [
MaterialPage(
key: ValueKey(DEFAULT_PAGE),
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(‘DEFAULT’),
),
drawer: ResourceDrawer(
resourceViewState: resourceViewState,
navKey: navigatorKey,
),
body: DefaultPage(),
),
),
if (selectedIndex != DEFAULT_PAGE) ...[
MaterialPage(
key: ValueKey(selectedIndex),
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(_getTitle(selectedIndex)),
),
drawer: ResourceDrawer(
deviceState: deviceState,
navKey: navigatorKey,
),
body: _getScreen(selectedIndex),
),
),
],
],
onPopPage: (route, result) {
if (result == "return") {
print("return ");
return route.didPop(true);
}
resourceViewState.selectedIndex = DEFAULT_PAGE;
notifyListeners();
return route.didPop(false);
},
);
}
我想在对话框中单击按钮时将用户从 Alert Dialog 导航到“Select 资源”页面。为此我必须这样做(参见图中的 1、2、3)。
如果用户从默认屏幕弹出,3 似乎由基本路由器处理,但我还需要从警报对话框中执行此操作。
- 弹出警报对话框
- 弹出 Material 设计抽屉
- 从嵌套路由器弹出到基本路由器。
这就是图中红色箭头所示的效果。
我可以简单地使用 Navigator.of(context).pop() 作为前两个。我很确定这里使用的 Navigator 与 Nested Router 使用的导航器不同(希望在这里了解一些细节).我相信是这种情况,因为在这些事件中不会为 NestedRouter 调用 onPopPage。
对于 3) 我试过这个策略:
a) 从导航抽屉中调用 navKey.currentState!.pop(“disconnected”)。我传入 Nested Router 的 navKey 如上面的代码所示。
b) 现在向嵌套路由器注册的 onPopPage 侦听器收到此 pop 事件的结果。
onPopPage: (route, result) {
if (result == "return") {
print("return ");
return route.didPop(true);
}
resourceViewState.selectedIndex = DEFAULT_PAGE;
notifyListeners();
return route.didPop(false);
},
当我看到结果 == "return" 时,我应该从“资源仪表板”页面导航到“Select 资源”页面。但我不确定该怎么做,也不知道在同一条路线(切线)上使用不同的视图是否是一个好策略。
这是一个可行的解决方案。我传递了对父导航器键的引用,然后从中调用 pop。我更希望它完全是声明性的,但我不确定如何使用嵌套导航器模式来实现。
class ResourcePage extends StatefulWidget {
ResourcePage({
required this.resourceViewState,
required this.navigatorKey,
});
final ResourceViewState resourceViewState;
final GlobalKey<NavigatorState> navigatorKey;
@override
_ResourcePageState createState() => _ResourcePageState();
}
class _ResourcePageState extends State<DevicePage> {
late DeviceDelegate _routerDelegate;
late ChildBackButtonDispatcher _backButtonDispatcher;
@override
void didChangeDependencies() {
super.didChangeDependencies();
// Defer back button dispatching to the child router
_routerDelegate = InnerRouterDelegate(parentNavigatorKey: widget.navigatorKey, resourceViewState: widget.resourceViewState);
_backButtonDispatcher = Router.of(context).backButtonDispatcher!.createChildBackButtonDispatcher();
_backButtonDispatcher.takePriority();
}
@override
void didUpdateWidget(covariant DevicePage oldWidget) {
super.didUpdateWidget(oldWidget);
_routerDelegate.state = widget.resourceViewState;
}
@override
Widget build(BuildContext context) {
return Router(
routerDelegate: _routerDelegate,
backButtonDispatcher: _backButtonDispatcher,
);
}
}
// InnerRouterDelegate Snippets
// Constructor
InnerRouterDelegate({
required this.resourceViewState,
required this.parentNavigatorKey,
}) {
resourceViewState.addListener(notifyListeners); // See Nested Navigation Example
}
// On Pop Page
onPopPage: (route, result) {
if (result == "return") {
parentNavigatorKey.currentState!.pop();
return route.didPop(true);
}
resourceViewState.selectedIndex = DEFAULT_PAGE;
notifyListeners();
return route.didPop(false);
},
我想使用 Flutter’s (2.0) navigation for routing on my mobile app. I cannot find cookbook examples and followed the recommended guide, implementing the nested router example。
注意===
如果呈现的视图在应用程序中具有唯一的路由 (uri),我将其称为页面。
如果它没有唯一的路线,我称之为屏幕。
========
基本路由器 select 在应用程序的页面之间。 “资源仪表板”中的嵌套路由器使用 resourceViewState 对象 select 屏幕在“资源仪表板”页面中呈现。只需使用如下所示的 selectedIndex,我就可以根据用户在 Material Design Drawer.
中 selected 的索引更改屏幕因此,当用户在上图中的任何非默认屏幕(即细节 A、细节 B)上,并且有弹出事件时,用户会 returned 到默认屏幕。如果用户从默认屏幕弹出,他们将 returned 到嵌套路由器之外的“Select 资源”页面。但是我还有一个棘手的案例要处理(或者我可能没有很好地处理这些案例:))
@override
Widget build(BuildContext context) {
int selectedIndex = resourceViewState.selectedIndex;
return Navigator(
key: navigatorKey,
pages: [
MaterialPage(
key: ValueKey(DEFAULT_PAGE),
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(‘DEFAULT’),
),
drawer: ResourceDrawer(
resourceViewState: resourceViewState,
navKey: navigatorKey,
),
body: DefaultPage(),
),
),
if (selectedIndex != DEFAULT_PAGE) ...[
MaterialPage(
key: ValueKey(selectedIndex),
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(_getTitle(selectedIndex)),
),
drawer: ResourceDrawer(
deviceState: deviceState,
navKey: navigatorKey,
),
body: _getScreen(selectedIndex),
),
),
],
],
onPopPage: (route, result) {
if (result == "return") {
print("return ");
return route.didPop(true);
}
resourceViewState.selectedIndex = DEFAULT_PAGE;
notifyListeners();
return route.didPop(false);
},
);
}
我想在对话框中单击按钮时将用户从 Alert Dialog 导航到“Select 资源”页面。为此我必须这样做(参见图中的 1、2、3)。
如果用户从默认屏幕弹出,3 似乎由基本路由器处理,但我还需要从警报对话框中执行此操作。
- 弹出警报对话框
- 弹出 Material 设计抽屉
- 从嵌套路由器弹出到基本路由器。
这就是图中红色箭头所示的效果。
我可以简单地使用 Navigator.of(context).pop() 作为前两个。我很确定这里使用的 Navigator 与 Nested Router 使用的导航器不同(希望在这里了解一些细节).我相信是这种情况,因为在这些事件中不会为 NestedRouter 调用 onPopPage。
对于 3) 我试过这个策略:
a) 从导航抽屉中调用 navKey.currentState!.pop(“disconnected”)。我传入 Nested Router 的 navKey 如上面的代码所示。
b) 现在向嵌套路由器注册的 onPopPage 侦听器收到此 pop 事件的结果。
onPopPage: (route, result) {
if (result == "return") {
print("return ");
return route.didPop(true);
}
resourceViewState.selectedIndex = DEFAULT_PAGE;
notifyListeners();
return route.didPop(false);
},
当我看到结果 == "return" 时,我应该从“资源仪表板”页面导航到“Select 资源”页面。但我不确定该怎么做,也不知道在同一条路线(切线)上使用不同的视图是否是一个好策略。
这是一个可行的解决方案。我传递了对父导航器键的引用,然后从中调用 pop。我更希望它完全是声明性的,但我不确定如何使用嵌套导航器模式来实现。
class ResourcePage extends StatefulWidget {
ResourcePage({
required this.resourceViewState,
required this.navigatorKey,
});
final ResourceViewState resourceViewState;
final GlobalKey<NavigatorState> navigatorKey;
@override
_ResourcePageState createState() => _ResourcePageState();
}
class _ResourcePageState extends State<DevicePage> {
late DeviceDelegate _routerDelegate;
late ChildBackButtonDispatcher _backButtonDispatcher;
@override
void didChangeDependencies() {
super.didChangeDependencies();
// Defer back button dispatching to the child router
_routerDelegate = InnerRouterDelegate(parentNavigatorKey: widget.navigatorKey, resourceViewState: widget.resourceViewState);
_backButtonDispatcher = Router.of(context).backButtonDispatcher!.createChildBackButtonDispatcher();
_backButtonDispatcher.takePriority();
}
@override
void didUpdateWidget(covariant DevicePage oldWidget) {
super.didUpdateWidget(oldWidget);
_routerDelegate.state = widget.resourceViewState;
}
@override
Widget build(BuildContext context) {
return Router(
routerDelegate: _routerDelegate,
backButtonDispatcher: _backButtonDispatcher,
);
}
}
// InnerRouterDelegate Snippets
// Constructor
InnerRouterDelegate({
required this.resourceViewState,
required this.parentNavigatorKey,
}) {
resourceViewState.addListener(notifyListeners); // See Nested Navigation Example
}
// On Pop Page
onPopPage: (route, result) {
if (result == "return") {
parentNavigatorKey.currentState!.pop();
return route.didPop(true);
}
resourceViewState.selectedIndex = DEFAULT_PAGE;
notifyListeners();
return route.didPop(false);
},