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

Flutter底部导航栏跳转页面后消失问题求助

底部导航栏跳转时保持显示的解决方案

问题原因

你遇到的问题是因为跳转时使用了全局导航栈(比如Get.to),新页面被推到了外层导航栈,直接覆盖了包含底部导航栏的Scaffold,导致底部导航栏消失。

核心解决方案:为每个Tab维护独立导航栈

你的代码已经为每个底部导航项创建了独立的Navigator和对应的navigatorKey,只需要修改跳转逻辑,使用当前Tab对应的导航器来push页面,而不是全局导航栈。

步骤1:在控制器中添加Tab内跳转方法

修改MainWrapperController,添加一个方法用于获取当前选中Tab的导航器并跳转:

class MainWrapperController extends GetxController {
  final Rx<int> _selectedIndex = 0.obs;

  int get selectedIndex => _selectedIndex.value;

  void setSelectedIndex(int index) => _selectedIndex.value = index;

  List<NavigationItemModel> navItemModels = [
    NavigationItemModel(
      navigatorKey: GlobalKey<NavigatorState>(),
      title: "Home",
      icon: Icons.home,
      page: const HomePage(),
    ),
    NavigationItemModel(
      navigatorKey: GlobalKey<NavigatorState>(),
      title: "Report",
      icon: Icons.equalizer,
      page: const ReportMenuPage(),
    ),
    NavigationItemModel(
      navigatorKey: GlobalKey<NavigatorState>(),
      title: "Profile",
      icon: Icons.person,
      page: const ProfilePage(),
    ),
  ];

  // 新增:向当前选中的Tab导航栈中push页面
  void pushToCurrentTab(Widget page) {
    navItemModels[selectedIndex].navigatorKey.currentState?.push(
      MaterialPageRoute(builder: (context) => page),
    );
  }
}

步骤2:修改HomePage的跳转逻辑

将Get.to替换为调用控制器的跳转方法:

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: ColorConstant.background,
        body: Column(
          children: [
            SimpleButtonWidget(
              onPressed: () {
                // 使用当前Tab的导航器跳转,而非全局导航栈
                Get.find<MainWrapperController>().pushToCurrentTab(const NextPage());
              },
              text: 'Click Me',
            )
          ],
        ));
  }
}

步骤3:优化NextPage(可选)

给NextPage添加Scaffold,保证页面结构完整:

class NextPage extends StatelessWidget {
  const NextPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Next Page")),
      body: const Center(child: Text("HELLO FROM NEXT PAGE")),
    );
  }
}

步骤4:修复返回键逻辑

修改MainWrapper中的PopScope,让返回键优先处理当前Tab的导航栈:

PopScope(
  canPop: false,
  onPopInvoked: (didPop) {
    final currentNavigator = mainWrapperController.navItemModels[mainWrapperController.selectedIndex].navigatorKey.currentState;
    if (currentNavigator != null && currentNavigator.canPop()) {
      // 当前Tab栈有页面,返回上一页
      currentNavigator.pop();
    } else {
      // 当前Tab栈为空,退出应用
      SystemNavigator.pop();
    }
  },
  child: Scaffold(...),
)

对你疑问的解答

  1. 是否不应再使用Navigator.push?
    不是不能用,而是要使用当前Tab对应的NavigatorState来调用push,而非全局的导航栈(比如Get.to默认使用全局导航栈,或者context.navigator获取的外层导航器)。

  2. 除了第三方包还有其他解决方案吗?
    当然有,你当前的代码已经具备了核心结构(每个Tab独立的Navigator),只需要调整跳转逻辑即可,完全不需要依赖第三方包。

  3. 原生setState实现时是否有遗漏?
    原生实现时如果没有为每个Tab创建独立的Navigator,而是直接切换页面,跳转时就会使用全局导航栈,导致底部导航栏被覆盖。你的代码已经做了独立导航栈的基础工作,只是跳转时没用到对应的导航器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 15:54:53