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
相关产品推荐
相关产品推荐

