如何用Flutter Go_Router实现倒L型网页框架?
用GoRouter实现倒L型布局的可行方案
方案思路
倒L型布局核心是顶部固定导航栏 + 左侧固定侧边栏 + 右下内容区,GoRouter的ShellRoute嵌套是最贴合路由设计的实现方式:
- 外层
ShellRoute负责渲染顶部导航栏,将侧边栏+页面内容作为子节点 - 内层
ShellRoute负责渲染左侧侧边栏,将实际页面内容作为子节点
这种嵌套结构能保证路由切换时,顶部、侧边栏常驻,仅内容区更新,完全符合单页应用的路由行为,比Stack+Positioned的纯布局方案更易维护扩展。
完整代码实现
基于你提供的现有代码,修改后实现倒L型布局:
import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; // 假设你已定义globals和Header组件 class globals { static const Color MenuBarBackgroundColor = Colors.grey; static const TextStyle MenuBarStyle = TextStyle(color: Colors.white); } class Header extends StatelessWidget { const Header({super.key}); @override Widget build(BuildContext context) { return Container( height: 100, color: Colors.blue, child: const Center(child: Text('Header Image')), ); } } // 左侧侧边栏组件 class LeftSidebar extends StatelessWidget { const LeftSidebar({super.key}); @override Widget build(BuildContext context) { return Container( width: 200, color: Colors.grey[200], child: Column( children: [ TextButton( onPressed: () => context.go('/dashboard'), child: const Text('Dashboard'), ), TextButton( onPressed: () => context.go('/settings'), child: const Text('Settings'), ), // 更多侧边栏菜单项 ], ), ); } } // 示例页面组件 class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return const Center(child: Text('Home Page Content')); } } class DashboardPage extends StatelessWidget { const DashboardPage({super.key}); @override Widget build(BuildContext context) { return const Center(child: Text('Dashboard Content')); } } class SettingsPage extends StatelessWidget { const SettingsPage({super.key}); @override Widget build(BuildContext context) { return const Center(child: Text('Settings Content')); } } final GoRouter _router = GoRouter( initialLocation: '/', routes: [ // 外层Shell:顶部导航栏 ShellRoute( builder: (context, state, child) { final screenWidth = MediaQuery.of(context).size.width; final menuSpacing = screenWidth * 0.01; return Scaffold( body: Padding( padding: EdgeInsets.symmetric(horizontal: screenWidth * 0.1), child: Column( children: [ const Header(), // 顶部Header Container( // 顶部导航栏 height: 50, color: globals.MenuBarBackgroundColor, child: Row( children: [ TextButton( onPressed: () => context.go("/"), child: const Text("Home", style: globals.MenuBarStyle), ), SizedBox(width: menuSpacing), TextButton( onPressed: () => context.go("/dashboard"), child: const Text("Dashboard", style: globals.MenuBarStyle), ), // 更多顶部菜单项 ], ), ), Expanded(child: child), // 内层Shell+页面内容在这里渲染 ], ), ), ); }, routes: [ // 内层Shell:左侧侧边栏 ShellRoute( builder: (context, state, child) { return Row( children: [ const LeftSidebar(), // 左侧固定侧边栏 Expanded(child: child), // 页面内容区 ], ); }, routes: [ // 具体页面路由 GoRoute( path: "/", builder: (context, state) => const HomePage(), ), GoRoute( path: "/dashboard", builder: (context, state) => const DashboardPage(), ), GoRoute( path: "/settings", builder: (context, state) => const SettingsPage(), ), ], ), ], ), ], ); // 主应用入口 class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp.router( routerConfig: _router, title: '倒L型布局Demo', ); } }
关键说明
嵌套ShellRoute的优势:
- 层级清晰,外层控顶部、内层控侧边栏,路由逻辑与布局完全分离
- 路由切换仅更新内容区,导航组件常驻,符合单页应用交互逻辑
- 后续扩展折叠侧边栏、响应式布局时,代码改动更集中
布局优化建议:
- 侧边栏宽度可通过
MediaQuery动态计算,适配不同设备 - 可结合状态管理(如Riverpod)实现侧边栏折叠功能
- 导航菜单统一用
context.go()跳转,保持路由行为一致性
- 侧边栏宽度可通过
为什么不选
Stack+Positioned:- 纯布局方案未结合路由嵌套逻辑,路由复杂时代码耦合度高
- ShellRoute是GoRouter专为"路由嵌套布局"设计的API,更契合框架设计理念
内容的提问来源于stack exchange,提问作者Tony Lam
相关产品推荐
相关产品推荐

