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

Flutter基于BottomNavigationBar的activeIndex动态切换Scaffold body不更新问题

问题根源
  • 状态归属错误:activeIndex存储在子组件BottomNavBar中,子组件调用setState只会刷新自身UI,父组件Dashboard无法感知到状态变化,因此Scaffold的body不会同步更新。
  • 跨组件直接读取状态不符合Flutter状态流转逻辑,父组件无法监听子组件内部的属性变更。
修复实现

步骤1:改造BottomNavBar组件

将其改为无状态组件,所有可变状态由父组件传入,点击操作通过回调通知父组件:

class BottomNavBar extends StatelessWidget {
  // 接收父组件传入的当前选中索引
  final int activeIndex;
  // 接收父组件传入的索引修改回调
  final Function(int) onIndexChanged;
  final Color primaryColor = const Color(0xff2FC4B2);
  final Color inactiveIconColor = Colors.white;
  final Color activeIconColor = Colors.blue;

  const BottomNavBar({
    Key? key,
    required this.activeIndex,
    required this.onIndexChanged,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      items: const [
        BottomNavigationBarItem(
            icon: Icon(
              Icons.track_changes_outlined,
              color: inactiveIconColor,
            ),
            activeIcon: Icon(
              Icons.track_changes_outlined,
              color: activeIconColor,
            ),
            label: "Track"),
        BottomNavigationBarItem(
            icon: Icon(
              Icons.home_outlined,
              color: inactiveIconColor,
            ),
            activeIcon: Icon(
              Icons.home_outlined,
              color: activeIconColor,
            ),
            label: "Home"),
        BottomNavigationBarItem(
            icon: Icon(
              Icons.settings_outlined,
              color: inactiveIconColor,
            ),
            activeIcon: Icon(
              Icons.settings_outlined,
              color: activeIconColor,
            ),
            label: "Settings")
      ],
      backgroundColor: primaryColor,
      fixedColor: Colors.white,
      showSelectedLabels: false,
      showUnselectedLabels: false,
      currentIndex: activeIndex,
      // 点击时触发父组件传入的回调
      onTap: onIndexChanged,
    );
  }
}

步骤2:改造Dashboard组件

将activeIndex作为自身状态管理,收到子组件回调时更新状态触发页面刷新:

class Dashboard extends StatefulWidget {
  final String? userID;
  final String? userName;

  const Dashboard(this.userID, this.userName, {Key? key}) : super(key: key);

  @override
  _DashboardState createState() => _DashboardState();
}

class _DashboardState extends State<Dashboard> {
  // 把选中索引存在父组件的状态中
  int _activeIndex = 1;
  // 页面列表提前初始化
  late List<Widget> _navBarItems;

  @override
  void initState() {
    super.initState();
    _navBarItems = [
      const Track(),
      Home(widget.userID, widget.userName),
      // 需补全第三个Settings页实现,避免下标越界
      const Settings()
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: BottomNavBar(
        activeIndex: _activeIndex,
        onIndexChanged: (index) {
          // 点击时更新父组件状态,触发整个页面刷新
          setState(() {
            _activeIndex = index;
          });
        },
      ),
      body: _navBarItems[_activeIndex],
    );
  }
}
注意事项
  • 原BottomNavigationBar配置了3个tab项,需补全第三个Settings页的实现,避免出现数组下标越界异常。
  • 页面列表不要放在build方法中初始化,避免每次页面刷新都重复创建页面实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 13:06:03