英文:
Flutter web app with Go Route and static Top Navigation Bar
问题
我已经在Flutter中为后端用户编写了一个Web应用程序,其中有一个侧边导航栏,并根据菜单选择返回不同的容器。现在我需要移植到一个需要页面路由(带有页面名称甚至参数的URL)并带有静态顶部菜单栏的前端Web应用程序。
我发现Go_Router包非常有用,但它只包含了一个带底部导航栏示例。我找到了一些创建静态顶部栏的示例,但没有使用Go_Router包。有人可以向我展示如何做到这一点吗?
简而言之,我想要一个Web应用程序,其中有一个静态顶部导航栏,URL会更改为子页面名称,其中一些可能需要接受参数。提前感谢。
英文:
I have written a web app in Flutter for backend users which have a side navigation bar and return different containers according to menu selections. Now I have to move to a front end web app that requires page routing (url with page names or even parameters) and with a static top menu bar.
I found package Go_Router quite useful but it only contains an example with bottom navigation bar. I found some examples in creating static top bar but not using Go_Router package. Can anyone show me the way how to do this?
In short again, I would like to have a web app that has a static top navigation bar, url changes to subpage names in which some may need to accept parameters as well. Thanks in advance.
答案1
得分: 1
我认为你可以使用shellRoute来实现这个功能。
在go_router中,Shell页面用于多部分路由。它们允许你为一组路由定义一个共享的框架。查看Flutter文档。
ShellRoute(
builder: (BuildContext context, GoRouterState state, Widget child) {
return Scaffold(
appBar: AppBar(
title: Text('App Shell')
),
body: Center(
child: child,
),
);
},
routes: [
GoRoute(
path: 'a'
builder: (BuildContext context, GoRouterState state) {
return Text('Child Route "/a"');
}
),
],
),
英文:
I think you can use shellRoute for this.
Shell pages in go_router are used for multi-part routes. They allow you to define a shared scaffold for a group of routes. check Flutter doc.
ShellRoute(
builder: (BuildContext context, GoRouterState state, Widget child) {
return Scaffold(
appBar: AppBar(
title: Text('App Shell')
),
body: Center(
child: child,
),
);
},
routes: [
GoRoute(
path: 'a'
builder: (BuildContext context, GoRouterState state) {
return Text('Child Route "/a"');
}
),
],
),
答案2
得分: 1
首先,你需要清晰地定义你的路径和路由层次结构,并理解 GoRouter 声明式导航词与命令式导航 的区别。
然后,你可以创建一个 GoRouter,如下所示:
// GoRouter 根导航键。
final GlobalKey<NavigatorState> _rootNavigatorKey = GlobalKey<NavigatorState>();
/// 导航路由。
final GoRouter kRouter = new GoRouter(
navigatorKey: _rootNavigatorKey,
initialLocation: "/",
routes: <RouteBase>[
// 主页面
new ShellRoute(
pageBuilder: (_, routerState, child) {
return new NoTransitionPage<void>(
key: routerState.pageKey,
child: new MainPage(body: child),
);
},
routes: [
new GoRoute(
name: "menu-1",
path: "/menu-1",
pageBuilder: (_, routerState) {
return new NoTransitionPage<void>(
key: routerState.pageKey,
child: const Menu1Page(),
);
},
),
new GoRoute(
name: "home",
path: "/",
pageBuilder: (_, routerState) {
return new NoTransitionPage<void>(
key: routerState.pageKey,
child: const HomePage(),
);
},
),
new GoRoute(
name: "menu-2",
path: "/menu-2",
pageBuilder: (_, routerState) {
return new NoTransitionPage<void>(
key: routerState.pageKey,
child: const Menu2Page(),
);
},
),
],
),
// 认证页面
new GoRoute(
parentNavigatorKey: _rootNavigatorKey,
name: "authentication",
path: "/authentication",
pageBuilder: (_, routerState) {
return new NoTransitionPage<void>(
key: routerState.pageKey,
child: const AuthenticationPage(),
);
},
),
// 用户配置页面
new GoRoute(
parentNavigatorKey: _rootNavigatorKey,
name: "settings",
path: "/settings",
builder: (_, routerState) {
return const SettingsPage();
},
),
],
refreshListenable: refreshabler, // 这个 ChangeNotifier 应该实现任何自定义的路由刷新,例如用户登录时的刷新。
// 在 redux 路由操作上刷新路由。
redirect: routerRedirect, // 这个函数应该实现你的重定向逻辑。
);
实现 MainPage
,它将成为包含 TopNavBar
的外壳页面。
// 导航栏键。
const Key _kBottomNavKey = ValueKey("bottom-nav-bar");
class MainPage extends StatelessWidget {
const MainPage({super.key, required this.body});
final Widget body;
@override
Widget build(BuildContext context) {
return new Column(
children: [
const TopNavBar(key: _kBottomNavKey),
new Expanded(child: body),
],
);
}
}
你的 TopNavBar
实现应该是一个 StatefulWidget,它通过 setState
和一个 "_current" 索引(例如)来跟踪当前显示的外壳页面。可以查看 Flutter 文档中的 NavigationBar。
英文:
You first need to clearly defined your paths and routes hierarchy, and understand how GoRouter declarative navigation words vs imperative navigation.
Then you can create a GoRouter as the following:
// GoRouter root navigator key.
final GlobalKey<NavigatorState> _rootNavigatorKey = GlobalKey<NavigatorState>();
/// Navigation router.
final GoRouter kRouter = new GoRouter(
navigatorKey: _rootNavigatorKey,
initialLocation: "/",
routes: <RouteBase>[
// Main page
new ShellRoute(
pageBuilder: (_, routerState, child) {
return new NoTransitionPage<void>(
key: routerState.pageKey,
child: new MainPage(body: child),
);
},
routes: [
new GoRoute(
name: "menu-1",
path: "/menu-1",
pageBuilder: (_, routerState) {
return new NoTransitionPage<void>(
key: routerState.pageKey,
child: const Menu1Page(),
);
},
),
new GoRoute(
name: "home",
path: "/",
pageBuilder: (_, routerState) {
return new NoTransitionPage<void>(
key: routerState.pageKey,
child: const HomePage(),
);
},
),
new GoRoute(
name: "menu-2",
path: "/menu-2",
pageBuilder: (_, routerState) {
return new NoTransitionPage<void>(
key: routerState.pageKey,
child: const Menu2Page(),
);
},
),
],
),
// Authentication page.
new GoRoute(
parentNavigatorKey: _rootNavigatorKey,
name: "authentication",
path: "/authentication",
pageBuilder: (_, routerState) {
return new NoTransitionPage<void>(
key: routerState.pageKey,
child: const AuthenticationPage(),
);
},
),
// User profile settings page.
new GoRoute(
parentNavigatorKey: _rootNavigatorKey,
name: "settings",
path: "/settings",
builder: (_, routerState) {
return const SettingsPage();
},
),
],
refreshListenable: refreshabler, // This ChangeNotifier shall implement any custom routing refresh, for example on user login.
// Refresh router on redux routing actions.
redirect: routerRedirect, // This function shall implement your redirection logic.
);
The implement MainPage
which will be your shell-page which contains the TopNavBar
.
// Navigation bar key.
const Key _kBottomNavKey = ValueKey("bottom-nav-bar");
class MainPage extends StatelessWidget {
const MainPage({super.key, required this.body});
final Widget body;
@override
Widget build(BuildContext context) {
return new Column(
children: [
const TopNavBar(key: _kBottomNavKey),
new Expanded(child: body),
],
);
}
}
Your TopNavBar
implemenation shall be a StatefulWidget which keeps track (using setState
and a "_current" index for example) of the currently displayed shelled page. Take a look at NavigationBar in the flutter documentation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论