김상현*_*김상현 23 android routes ios dart flutter
\n
如何使用导航栏按钮之一从 ShellRoute 推送到与 ShellRoute 同一层次结构中的 GoRoute?
\n目前GoRouter的路由有两个值:ShellRoute和GoRoute。ShellRoute 中的 Child 代表 Home、Discover 和 Shop Widget。然而,除了上面提到的 Widget 的三个按钮之外,NavBar 还多了一个第四个按钮。这个按钮(MY)用于转到前面提到的 GoRoute。
\n正如您从下面附加的代码中看到的,我希望在 ShellRoute 上按下第四个按钮时显示登录小部件,因为 GoRoute 堆叠在 ShellRoute 上。但实际上,随着 ShellRoute 被删除,GoRoute 成为顶部堆栈,iOS 没有后退按钮,Android 在 BackPress 时关闭应用程序。
\n官方文档examples中没有这方面的例子,所以我迷失了很多。\n我发现了类似的例子一万个\n https://github.com/flutter/packages/blob/main/packages/go_router/示例/lib/shell_route.dart \n在上面的示例中,GoRoute 依赖于 ShellRoute。\n我不想要这个。我想让登录路线可以从任何地方访问。
\n我将在下面附上我的代码和操作屏幕。\n我需要你的帮助。
\n预期成绩: \n当按下第四个按钮时,GoRoute 堆叠在 ShellRoute 上,按下背面时 ShellRoute 重新出现
\n实际结果: \n当按下第四个按钮时,ShellRoute 被移除,创建一个 GoRoute 并将其堆叠在顶部,当您按 Back 时应用程序结束。
\n
Performing hot restart...\nSyncing files to device iPhone 12...\nRestarted application in 368ms.\nflutter: MyTest didPush: _PageBasedMaterialPageRoute<void>(MaterialPage<void>("/", [<\'280748962\'>], {}), animation: AnimationController#0adb5(\xe2\x8f\xad 1.000; paused; for _PageBasedMaterialPageRoute<void>(/)))\nflutter: MyTest didPush: _PageBasedMaterialPageRoute<void>(MaterialPage<void>("/login", [<\'621841910\'>], {}), animation: AnimationController#4775c(\xe2\x96\xb6 0.000; for _PageBasedMaterialPageRoute<void>(/login)))\nflutter: MyTest didRemove: _PageBasedMaterialPageRoute<void>(MaterialPage<void>("/shop", [<\'280748962\'>], {}), animation: AnimationController#0adb5(\xe2\x8f\xad 1.000; paused; for _PageBasedMaterialPageRoute<void>(/)))\nRun Code Online (Sandbox Code Playgroud)\n\n代码示例\n\n主程序.dart
\nPerforming hot restart...\nSyncing files to device iPhone 12...\nRestarted application in 368ms.\nflutter: MyTest didPush: _PageBasedMaterialPageRoute<void>(MaterialPage<void>("/", [<\'280748962\'>], {}), animation: AnimationController#0adb5(\xe2\x8f\xad 1.000; paused; for _PageBasedMaterialPageRoute<void>(/)))\nflutter: MyTest didPush: _PageBasedMaterialPageRoute<void>(MaterialPage<void>("/login", [<\'621841910\'>], {}), animation: AnimationController#4775c(\xe2\x96\xb6 0.000; for _PageBasedMaterialPageRoute<void>(/login)))\nflutter: MyTest didRemove: _PageBasedMaterialPageRoute<void>(MaterialPage<void>("/shop", [<\'280748962\'>], {}), animation: AnimationController#0adb5(\xe2\x8f\xad 1.000; paused; for _PageBasedMaterialPageRoute<void>(/)))\nRun Code Online (Sandbox Code Playgroud)\nscaffold_with_nav_bar.dart
\nvoid main() {\n runApp(const MyApp());\n}\n\nfinal _rootNavigatorKey = GlobalKey<NavigatorState>();\nfinal _shellNavigatorKey = GlobalKey<NavigatorState>();\n\nfinal _router = GoRouter(\n initialLocation: \'/\',\n navigatorKey: _rootNavigatorKey,\n observers: [\n GoRouterObserver(),\n ],\n routes: [\n ShellRoute(\n navigatorKey: _shellNavigatorKey,\n builder: (context, state, child) {\n return ScaffoldWithNavBar(child: child);\n },\n routes: [\n GoRoute(\n path: \'/\',\n builder: (context, state) {\n return const Home();\n },\n ),\n GoRoute(\n path: \'/discover\',\n builder: (context, state) {\n return const Discover();\n },\n ),\n GoRoute(\n path: \'/shop\',\n builder: (context, state) {\n return const Shop();\n }),\n ],\n ),\n GoRoute(\n path: \'/login\',\n builder: (context, state) {\n return const Login();\n },\n ),\n ],\n);\n\nclass GoRouterObserver extends NavigatorObserver {\n @override\n void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {\n print(\'MyTest didPush: $route\');\n }\n\n @override\n void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {\n print(\'MyTest didPop: $route\');\n }\n\n @override\n void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {\n print(\'MyTest didRemove: $route\');\n }\n\n @override\n void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {\n print(\'MyTest didReplace: $newRoute\');\n }\n}\n\nclass MyApp extends StatelessWidget {\n const MyApp({super.key});\n\n // This widget is the root of your application.\n @override\n Widget build(BuildContext context) {\n return MaterialApp.router(\n title: \'Platform\',\n theme: ThemeData(\n primarySwatch: Colors.blue,\n ),\n routerConfig: _router,\n );\n }\n}\n\nRun Code Online (Sandbox Code Playgroud)\n\n\n 日志\n\n\n info \xe2\x80\xa2 Avoid `print` calls in production code \xe2\x80\xa2 lib/main.dart:62:5 \xe2\x80\xa2 avoid_print\n info \xe2\x80\xa2 Avoid `print` calls in production code \xe2\x80\xa2 lib/main.dart:67:5 \xe2\x80\xa2 avoid_print\n info \xe2\x80\xa2 Avoid `print` calls in production code \xe2\x80\xa2 lib/main.dart:72:5 \xe2\x80\xa2 avoid_print\n info \xe2\x80\xa2 Avoid `print` calls in production code \xe2\x80\xa2 lib/main.dart:77:5 \xe2\x80\xa2 avoid_print\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/discover/discover.dart:11:16 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Avoid using private types in public APIs \xe2\x80\xa2 lib/sections/exhibition/detail_exhibition.dart:10:3 \xe2\x80\xa2 library_private_types_in_public_api\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/exhibition/exhibition.dart:11:16 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Unused import: \'package:knowd_platform/sections/discover/discover.dart\' \xe2\x80\xa2 lib/sections/home/home.dart:2:8 \xe2\x80\xa2 unused_import\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/home/home.dart:21:15 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/login/login.dart:11:16 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/login/login_router.dart:8:34 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/login/singup.dart:11:16 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Avoid using private types in public APIs \xe2\x80\xa2 lib/sections/main_tab_bar.dart:12:3 \xe2\x80\xa2 library_private_types_in_public_api\n info \xe2\x80\xa2 Private field could be final \xe2\x80\xa2 lib/sections/main_tab_bar.dart:17:16 \xe2\x80\xa2 prefer_final_fields\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:18:5 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:19:5 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:20:5 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:21:5 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:41:18 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const literals as parameters of constructors on @immutable classes \xe2\x80\xa2 lib/sections/main_tab_bar.dart:59:17 \xe2\x80\xa2 prefer_const_literals_to_create_immutables\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:60:13 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:61:21 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:64:13 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:65:21 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:68:13 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:69:21 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:72:13 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:73:21 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/shop.dart:10:16 \xe2\x80\xa2 prefer_const_constructors\nRun Code Online (Sandbox Code Playgroud)\n\n info \xe2\x80\xa2 Avoid `print` calls in production code \xe2\x80\xa2 lib/main.dart:62:5 \xe2\x80\xa2 avoid_print\n info \xe2\x80\xa2 Avoid `print` calls in production code \xe2\x80\xa2 lib/main.dart:67:5 \xe2\x80\xa2 avoid_print\n info \xe2\x80\xa2 Avoid `print` calls in production code \xe2\x80\xa2 lib/main.dart:72:5 \xe2\x80\xa2 avoid_print\n info \xe2\x80\xa2 Avoid `print` calls in production code \xe2\x80\xa2 lib/main.dart:77:5 \xe2\x80\xa2 avoid_print\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/discover/discover.dart:11:16 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Avoid using private types in public APIs \xe2\x80\xa2 lib/sections/exhibition/detail_exhibition.dart:10:3 \xe2\x80\xa2 library_private_types_in_public_api\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/exhibition/exhibition.dart:11:16 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Unused import: \'package:knowd_platform/sections/discover/discover.dart\' \xe2\x80\xa2 lib/sections/home/home.dart:2:8 \xe2\x80\xa2 unused_import\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/home/home.dart:21:15 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/login/login.dart:11:16 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/login/login_router.dart:8:34 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/login/singup.dart:11:16 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Avoid using private types in public APIs \xe2\x80\xa2 lib/sections/main_tab_bar.dart:12:3 \xe2\x80\xa2 library_private_types_in_public_api\n info \xe2\x80\xa2 Private field could be final \xe2\x80\xa2 lib/sections/main_tab_bar.dart:17:16 \xe2\x80\xa2 prefer_final_fields\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:18:5 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:19:5 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:20:5 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:21:5 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:41:18 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const literals as parameters of constructors on @immutable classes \xe2\x80\xa2 lib/sections/main_tab_bar.dart:59:17 \xe2\x80\xa2 prefer_const_literals_to_create_immutables\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:60:13 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:61:21 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:64:13 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:65:21 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:68:13 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:69:21 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:72:13 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/main_tab_bar.dart:73:21 \xe2\x80\xa2 prefer_const_constructors\n info \xe2\x80\xa2 Prefer const with constant constructors \xe2\x80\xa2 lib/sections/shop.dart:10:16 \xe2\x80\xa2 prefer_const_constructors\n\nRun Code Online (Sandbox Code Playgroud)\n\n\n
kri*_*yaa 34
使用context.go()fromShellRoute到时要考虑的事项GoRoute
parentNavigatorKeypropGoRoute
ShellRoute:parentNavigatorKey:_shellNavigatorKeyMainRoute:parentNavigatorKey:_rootNavigatorKeycontext.go()替换页面,context.push()将页面压入堆栈代码结构如下:
final _parentKey = GlobalKey<NavigatorState>();
final _shellKey = GlobalKey<NavigatorState>();
|_ GoRoute
|_ parentNavigatorKey = _parentKey Specify key here
|_ ShellRoute
|_ GoRoute // Needs Bottom Navigation
|_ parentNavigatorKey = _shellKey
|_ GoRoute // Needs Bottom Navigation
|_ parentNavigatorKey = _shellKey
|_ GoRoute // Full Screen which doesn't need Bottom Navigation
|_parentNavigatorKey = _parentKey
Run Code Online (Sandbox Code Playgroud)
您的代码中的错误
未指定parentNavigatorKey
为了backButton可见,你必须有appBar内在Scaffold。
这段代码
if (index == 3) {
router.push(location);
}
setState(() {
_currentIndex = index;
router.go(location);
});
}
Run Code Online (Sandbox Code Playgroud)
代码改进
Navigation单击后退按钮时保留菜单navbar代码:
路由器
final _rootNavigatorKey = GlobalKey<NavigatorState>();
final _shellNavigatorKey = GlobalKey<NavigatorState>();
final router = GoRouter(
initialLocation: '/',
navigatorKey: _rootNavigatorKey,
routes: [
ShellRoute(
navigatorKey: _shellNavigatorKey,
pageBuilder: (context, state, child) {
print(state.location);
return NoTransitionPage(
child: ScaffoldWithNavBar(
location: state.location,
child: child,
));
},
routes: [
GoRoute(
path: '/',
parentNavigatorKey: _shellNavigatorKey,
pageBuilder: (context, state) {
return const NoTransitionPage(
child: Scaffold(
body: Center(child: Text("Home")),
),
);
},
),
GoRoute(
path: '/discover',
parentNavigatorKey: _shellNavigatorKey,
pageBuilder: (context, state) {
return const NoTransitionPage(
child: Scaffold(
body: Center(child: Text("Discover")),
),
);
},
),
GoRoute(
parentNavigatorKey: _shellNavigatorKey,
path: '/shop',
pageBuilder: (context, state) {
return const NoTransitionPage(
child: Scaffold(
body: Center(child: Text("Shop")),
),
);
}),
],
),
GoRoute(
parentNavigatorKey: _rootNavigatorKey,
path: '/login',
pageBuilder: (context, state) {
return NoTransitionPage(
key: UniqueKey(),
child: Scaffold(
appBar: AppBar(),
body: const Center(
child: Text("Login"),
),
),
);
},
),
],
);
Run Code Online (Sandbox Code Playgroud)
底部导航栏
class ScaffoldWithNavBar extends StatefulWidget {
String location;
ScaffoldWithNavBar({super.key, required this.child, required this.location});
final Widget child;
@override
State<ScaffoldWithNavBar> createState() => _ScaffoldWithNavBarState();
}
class _ScaffoldWithNavBarState extends State<ScaffoldWithNavBar> {
int _currentIndex = 0;
static const List<MyCustomBottomNavBarItem> tabs = [
MyCustomBottomNavBarItem(
icon: Icon(Icons.home),
activeIcon: Icon(Icons.home),
label: 'HOME',
initialLocation: '/',
),
MyCustomBottomNavBarItem(
icon: Icon(Icons.explore_outlined),
activeIcon: Icon(Icons.explore),
label: 'DISCOVER',
initialLocation: '/discover',
),
MyCustomBottomNavBarItem(
icon: Icon(Icons.storefront_outlined),
activeIcon: Icon(Icons.storefront),
label: 'SHOP',
initialLocation: '/shop',
),
MyCustomBottomNavBarItem(
icon: Icon(Icons.account_circle_outlined),
activeIcon: Icon(Icons.account_circle),
label: 'MY',
initialLocation: '/login',
),
];
@override
Widget build(BuildContext context) {
const labelStyle = TextStyle(fontFamily: 'Roboto');
return Scaffold(
body: SafeArea(child: widget.child),
bottomNavigationBar: BottomNavigationBar(
selectedLabelStyle: labelStyle,
unselectedLabelStyle: labelStyle,
selectedItemColor: const Color(0xFF434343),
selectedFontSize: 12,
unselectedItemColor: const Color(0xFF838383),
showUnselectedLabels: true,
type: BottomNavigationBarType.fixed,
onTap: (int index) {
_goOtherTab(context, index);
},
currentIndex: widget.location == '/'
? 0
: widget.location == '/discover'
? 1
: widget.location == '/shop'
? 2
: 3,
items: tabs,
),
);
}
void _goOtherTab(BuildContext context, int index) {
if (index == _currentIndex) return;
GoRouter router = GoRouter.of(context);
String location = tabs[index].initialLocation;
setState(() {
_currentIndex = index;
});
if (index == 3) {
context.push('/login');
} else {
router.go(location);
}
}
}
class MyCustomBottomNavBarItem extends BottomNavigationBarItem {
final String initialLocation;
const MyCustomBottomNavBarItem(
{required this.initialLocation,
required Widget icon,
String? label,
Widget? activeIcon})
: super(icon: icon, label: label, activeIcon: activeIcon ?? icon);
}
Run Code Online (Sandbox Code Playgroud)
输出:
| 归档时间: |
|
| 查看次数: |
16464 次 |
| 最近记录: |