基于GetX的Flutter Web侧边栏与AppBar持久化及浏览器导航处理
解决GetX+Flutter Web中侧边栏/AppBar持久化与浏览器路由响应问题
一、侧边栏与AppBar跨页面持久化方案
核心思路是将AppBar和Drawer固定在父级布局中,仅动态切换Scaffold的body区域内容,避免页面切换时重建顶部和侧边组件。
1. 创建全局状态控制器
用GetX管理当前页面和侧边栏选中状态:
class AppController extends GetxController { final RxInt selectedMenuIndex = 0.obs; final Rx<Widget> currentPage = const HomePage().obs; // 切换页面并同步路由与菜单选中状态 void switchPage(Widget page, int index, String routeName) { currentPage.value = page; selectedMenuIndex.value = index; Get.offNamed(routeName); // 更新浏览器地址栏路由 } }
2. 父级持久化布局
将AppBar、Drawer与可切换的body整合到主布局:
class MainLayout extends GetView<AppController> { const MainLayout({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Obx(() => Text(controller.currentPage.value.pageTitle)), // 这里的AppBar内容会根据当前页面动态更新,但组件本身不会重建 ), drawer: Drawer( child: ListView( children: [ const DrawerHeader(child: Text('系统菜单')), ListTile( title: const Text('首页'), selected: controller.selectedMenuIndex.value == 0, onTap: () { controller.switchPage(const HomePage(), 0, HomePage.routeName); Get.back(); // 关闭抽屉 }, ), ListTile( title: const Text('设置页'), selected: controller.selectedMenuIndex.value == 1, onTap: () { controller.switchPage(const SettingsPage(), 1, SettingsPage.routeName); Get.back(); }, ), ], ), ), // 仅body区域随状态切换,AppBar和Drawer始终保持 body: Obx(() => controller.currentPage.value), ); } }
3. 子页面定义
每个子页面需包含路由名称和页面标题:
class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key); static const routeName = '/home'; final String pageTitle = '首页'; @override Widget build(BuildContext context) { return const Center(child: Text('首页内容')); } }
二、浏览器前进后退按钮响应方案
通过配置GetX路由监听,同步路由变化与AppController的状态,实现浏览器导航操作与页面状态的联动。
1. 全局路由配置
在main函数中配置GetMaterialApp路由,所有子页面路由指向主布局:
void main() { Get.put(AppController()); // 初始化全局控制器 runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return GetMaterialApp( title: 'Flutter Web Demo', initialRoute: HomePage.routeName, getPages: [ GetPage(name: HomePage.routeName, page: () => const MainLayout()), GetPage(name: SettingsPage.routeName, page: () => const MainLayout()), ], // 监听路由变化,同步更新控制器状态 onGenerateRoute: (settings) { final controller = Get.find<AppController>(); switch(settings.name) { case HomePage.routeName: controller.switchPage(const HomePage(), 0, HomePage.routeName); break; case SettingsPage.routeName: controller.switchPage(const SettingsPage(), 1, SettingsPage.routeName); break; } return MaterialPageRoute(builder: (_) => const MainLayout()); }, ); } }
2. 路由监听增强
在AppController中添加路由监听,确保前进后退时状态完全同步:
class AppController extends GetxController { // ... 原有代码 @override void onInit() { super.onInit(); // 监听GetX路由变化,实时同步页面状态 ever(Get.routing, (route) { final currentRoute = route.current; if(currentRoute == HomePage.routeName) { switchPage(const HomePage(), 0, HomePage.routeName); } else if(currentRoute == SettingsPage.routeName) { switchPage(const SettingsPage(), 1, SettingsPage.routeName); } }); } }
内容的提问来源于stack exchange,提问作者Pankaj Tungaria
相关产品推荐
相关产品推荐

