You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中结合Getx Pages与固定Google NavBar的实现问题

解决方案

核心思路

把固定的AppBar和google_nav_bar放在外层Scaffold中,内部仅切换页面的主体内容,避免每个页面重复构建Scaffold导致的导航栏重载动画。结合GetX的状态管理控制页面切换,同时兼容GetPages路由配置。

步骤1:定义路由与状态管理控制器

创建GetX控制器管理底部导航选中索引,同时配置全局GetPages:

class NavController extends GetxController {
  final currentIndex = 0.obs;
  // 对应底部导航的页面路由名称
  final pages = [
    '/home',
    '/profile',
    '/settings',
  ];
}

void main() {
  Get.put(NavController());
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Demo',
      getPages: [
        GetPage(name: '/', page: () => MainScreen()),
        GetPage(name: '/home', page: () => HomePage()),
        GetPage(name: '/profile', page: () => ProfilePage()),
        GetPage(name: '/settings', page: () => SettingsPage()),
      ],
      initialRoute: '/',
    );
  }
}

步骤2:构建外层主页面(固定导航栏)

MainScreen作为外层容器,包含固定的AppBar和google_nav_bar,内部用嵌套导航器切换页面:

class MainScreen extends StatelessWidget {
  final navController = Get.find<NavController>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 仅在这里定义一次固定AppBar
      appBar: AppBar(
        title: const Text('固定导航栏'),
        centerTitle: true,
      ),
      // google_nav_bar底部导航
      bottomNavigationBar: Obx(() => GNav(
            selectedIndex: navController.currentIndex.value,
            onTabChange: (index) {
              navController.currentIndex.value = index;
              // 跳转对应子页面
              Get.toNamed(navController.pages[index], id: 1);
            },
            tabs: const [
              GButton(icon: Icons.home, text: '首页'),
              GButton(icon: Icons.person, text: '我的'),
              GButton(icon: Icons.settings, text: '设置'),
            ],
          )),
      // 嵌套导航器:仅在body区域切换页面,不影响外层导航栏
      body: Navigator(
        key: Get.nestedKey(1),
        initialRoute: '/home',
        onGenerateRoute: (settings) {
          return GetPageRoute(
            settings: settings,
            page: () {
              switch (settings.name) {
                case '/home':
                  return HomePage();
                case '/profile':
                  return ProfilePage();
                case '/settings':
                  return SettingsPage();
                default:
                  return HomePage();
              }
            },
          );
        },
      ),
    );
  }
}

步骤3:子页面仅实现主体内容

子页面无需包含Scaffold,只返回页面核心内容即可:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('首页内容'));
  }
}

class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('个人中心内容'));
  }
}

class SettingsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('设置页面内容'));
  }
}

关键说明

  • 用嵌套导航器(Get.nestedKey)将页面切换限制在body区域,外层AppBar和底部导航完全独立,不会随页面切换重建。
  • 通过Obx监听索引变化,实时更新底部导航选中状态,同时触发路由跳转。
  • 子页面去掉冗余Scaffold,彻底避免导航栏重复构建导致的动画干扰。

内容的提问来源于stack exchange,提问作者byraychen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 02:25:13