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

Flutter setState失效问题:BottomNavigationBar按钮点击不切换颜色

问题根源

你遇到的核心问题是点击按钮时调用了Navigator.push打开新页面——这会把包含BottomBar的原页面压入导航栈底部,此时用户看到的是新跳转的页面,原页面的setState更新的是栈底页面的状态,自然无法在当前视图中体现颜色变化。同时这种方式会不断创建新页面实例,完全不符合底部导航栏切换内容的预期逻辑。

另外你的screens数组顺序和currentTab的映射不匹配:currentTab=2对应NftPage,但screens里第三个元素是PeoplePage,会导致后续切换页面时出现错误。

修复方案

1. 调整页面切换逻辑,移除Navigator.push

底部导航栏的正确逻辑是在同一个页面内切换body内容,而不是打开新页面。需要将BottomBar作为Scaffold的bottomNavigationBar,body部分直接显示当前选中的页面。

2. 修正screens数组与currentTab的映射

确保数组顺序和currentTab的取值一一对应:

final List<Widget> screens = [
  HomePage(),
  ShopPage(),
  NftPage(), // 对应currentTab=2
  PeoplePage(), // 对应currentTab=3
];

3. 优化状态更新逻辑

直接通过currentTab从screens数组获取页面,避免重复创建实例。

修改后的完整代码示例
class BottomBar extends StatefulWidget {
  @override
  State<BottomBar> createState() => BottomBarState();
}

class BottomBarState extends State<BottomBar> {
  int currentTab = 0;
  final PageStorageBucket bucket = PageStorageBucket();
  // 修正screens数组顺序,与currentTab一一对应
  final List<Widget> screens = [
    HomePage(),
    ShopPage(),
    NftPage(),
    PeoplePage(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageStorage(
        bucket: bucket,
        child: screens[currentTab], // 直接显示当前选中的页面
      ),
      bottomNavigationBar: BottomAppBar(
        shape: const CircularNotchedRectangle(),
        notchMargin: 10,
        child: Container(
          height: 60,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  MaterialButton(
                    minWidth: 40,
                    onPressed: () {
                      setState(() {
                        currentTab = 0;
                      });
                    },
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.home,
                          color: currentTab == 0 ? Colors.blue : Colors.grey,
                        ),
                      ],
                    ),
                  ),
                  MaterialButton(
                    minWidth: 40,
                    onPressed: () {
                      setState(() {
                        currentTab = 1;
                      });
                    },
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.shopping_bag_outlined,
                          color: currentTab == 1 ? Colors.blue : Colors.grey,
                        ),
                      ],
                    ),
                  ),
                ],
              ),
              // Right Tab Bar Icons
              Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  MaterialButton(
                    minWidth: 40,
                    onPressed: () {
                      setState(() {
                        currentTab = 2;
                      });
                    },
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.account_balance_wallet,
                          color: currentTab == 2 ? Colors.blue : Colors.grey,
                        ),
                      ],
                    ),
                  ),
                  MaterialButton(
                    minWidth: 40,
                    onPressed: () {
                      setState(() {
                        currentTab = 3;
                      });
                    },
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.people,
                          color: currentTab == 3 ? Colors.blue : Colors.grey,
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}
额外说明

如果你的BottomBar原本是作为子组件嵌入到其他Scaffold中的,那么需要把currentTab和screens的状态提升到父组件,或者通过回调通知父组件切换页面,确保BottomBar和页面内容处于同一个上下文环境中。使用PageStorage可以保留每个页面的滚动状态,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 03:55:39