带有 go_router 的 NavigationRail

Dar*_*arc 6 flutter flutter-web flutter-go-router

我正在开发一个 Web/桌面应用程序,它具有相当标准的 UI 布局,包括NavigationRail左侧的 和占据屏幕其余部分的内容窗格。

在此输入图像描述

我最近添加了这样的内容go_router,这样我就可以在网络浏览器中正确支持 URL,但是这样做时,我在页面之间移动时失去了任何形式的过渡/动画的能力,因为调用会context.go()导致硬切到下一页。

还有一个问题是,go_router路由必须返回要呈现的完整页面,这意味着我需要在每个页面上包含导航栏,而不是每个页面只是与该页面相关的内容。我相信这也是所有动画被破坏的主要原因,因为单击链接会有效地破坏当前的导航栏并为新页面构建新的导航栏

我看不到任何内容go_router,但是否有任何形式的构建器 API 可以输出和刷新页面的单个部分?我正在考虑类似bloc's 的东西BlocBuilder,它侦听状态更改并仅在发生更改时重建其负责的小部件。

或者,有没有办法在不重建整个页面的情况下更新当前 URL?

或者go_router只是无法实现我所追求的目标,如果是这样,是否有其他替代方案可以做到这一点?

我所追求的整体效果类似于材料网站https://m3.material.io/develop 单击各个按钮感觉就像您在应用程序中导航,而不是单击链接并加载新页面

感谢您的帮助

Ben*_*ins 1

我用 Shell Route 解决了这个问题。我在阅读go_router 5 迁移指南时得到了这个想法。我看到他们有一个navigatorBuilder属性,他们将每条路线都用 AppBar 包装在脚手架中。它说要迁移:

迁移前:

final GoRouter router = GoRouter(
 routes: <GoRoute> [
   GoRoute(
     path: '/',
     builder: (_, __) => const Text('/'),
   ),
   GoRoute(
     path: '/a',
     builder: (_, __) => const Text('/a'),
   )
 ],
 navigatorBuilder: (BuildContext context, GoRouterState state, Widget child) {
   return Scaffold(
     appBar: AppBar(title: Text(state.location)),
     body: child,
   );
 }
);
Run Code Online (Sandbox Code Playgroud)

迁移后:

final GoRouter router = GoRouter(
 routes: <GoRoute> [
   ShellRoute(
     builder: (_, GoRouterState state, child) {
       return Scaffold(
         body: child, 
         appBar: AppBar(title: Text(state.location)),
       );
     },
     routes: [
       GoRoute(
         path: 'a',
         builder: (_, __) => const Text('a'),
       ),
       GoRoute(
         path: 'b',
         builder: (_, __) => const Text('b'),
       )
     ],
   ),
 ],
);
Run Code Online (Sandbox Code Playgroud)

现在,属性中的每条路线ShellRoute.routes都将用Scaffold和包裹AppBar,它不会在导航时重建,因此将表现为持久的AppBarNavigationBar或任何应该的行为。context.go('some_route')现在,当您执行此操作时(例如从NavigationBar中的 a ) ,它会显示页面转换动画ShellRoute。您也不会遇到 Felix ZYGoRoutercontext.

ANavigationRail在 shell 路由中就像这样:

ShellRoute(
 builder: (_, GoRouterState state, child) {
   return Scaffold(
  body: Column(children:[Row(
    children: <Widget>[
      NavigationRail(....)]),
  child,]));
});
Run Code Online (Sandbox Code Playgroud)

}