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

