Flutter Web应用程序具有Go路由和静态顶部导航栏

huangapple go评论68阅读模式
英文:

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&lt;NavigatorState&gt; _rootNavigatorKey = GlobalKey&lt;NavigatorState&gt;();

/// Navigation router.
final GoRouter kRouter = new GoRouter(
  navigatorKey: _rootNavigatorKey,
  initialLocation: &quot;/&quot;,
  routes: &lt;RouteBase&gt;[
    // Main page
    new ShellRoute(
      pageBuilder: (_, routerState, child) {
        return new NoTransitionPage&lt;void&gt;(
          key: routerState.pageKey,
          child: new MainPage(body: child),
        );
      },
      routes: [
        new GoRoute(
          name: &quot;menu-1&quot;,
          path: &quot;/menu-1&quot;,
          pageBuilder: (_, routerState) {
            return new NoTransitionPage&lt;void&gt;(
              key: routerState.pageKey,
              child: const Menu1Page(),
            );
          },
        ),
        new GoRoute(
          name: &quot;home&quot;,
          path: &quot;/&quot;,
          pageBuilder: (_, routerState) {
            return new NoTransitionPage&lt;void&gt;(
              key: routerState.pageKey,
              child: const HomePage(),
            );
          },
        ),
        new GoRoute(
          name: &quot;menu-2&quot;,
          path: &quot;/menu-2&quot;,
          pageBuilder: (_, routerState) {
            return new NoTransitionPage&lt;void&gt;(
              key: routerState.pageKey,
              child: const Menu2Page(),
            );
          },
        ),
      ],
    ),
    // Authentication page.
    new GoRoute(
      parentNavigatorKey: _rootNavigatorKey,
      name: &quot;authentication&quot;,
      path: &quot;/authentication&quot;,
      pageBuilder: (_, routerState) {
        return new NoTransitionPage&lt;void&gt;(
          key: routerState.pageKey,
          child: const AuthenticationPage(),
        );
      },
    ),
    // User profile settings page.
    new GoRoute(
      parentNavigatorKey: _rootNavigatorKey,
      name: &quot;settings&quot;,
      path: &quot;/settings&quot;,
      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(&quot;bottom-nav-bar&quot;);

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.

huangapple
  • 本文由 发表于 2023年6月13日 12:40:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76461730.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定