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

Flutter中BottomNavigationBar的currentIndex为何无法更新?

问题分析与解决

你的问题核心是每个页面都独立实例化了MyBottomNavBar,每个导航栏都维护自己的_selectedIndex状态。当通过Navigator.pushNamed跳转到新页面时,新页面的导航栏是全新实例,它的_selectedIndex会被初始化为0,所以无论之前怎么点击,新页面的导航栏始终显示Home为选中状态。

解决方法

方案一:单页面+Body切换(推荐)

这是BottomNavigationBar的标准用法,无需路由跳转,在一个主页面中根据选中索引切换Body内容,导航栏状态唯一且持续:

  1. 重构主页面结构,整合导航栏与页面切换逻辑:
class MainScreen extends StatefulWidget {
  const MainScreen({Key? key}) : super(key: key);

  @override
  State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  int _selectedIndex = 0;

  // 与导航栏索引对应的页面列表
  final List<Widget> _pages = const [
    MyHomePage(title: "STFU"),
    Play(),
    Create(),
  ];

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _pages[_selectedIndex],
      bottomNavigationBar: BottomNavigationBar(
        backgroundColor: Colors.orangeAccent[100],
        currentIndex: _selectedIndex,
        onTap: _onItemTapped,
        items: const [
          BottomNavigationBarItem(label: "Home", icon: Icon(Icons.home_filled)),
          BottomNavigationBarItem(label: "Play", icon: Icon(Icons.play_arrow_rounded)),
          BottomNavigationBarItem(label: "Create", icon: Icon(Icons.create)),
        ],
      ),
    );
  }
}
  1. 修改main.dart路由配置,将MainScreen设为初始路由:
routes: {
  "/": (context) => const MainScreen(),
  "/settings": (context) => Settings(),
},

这种方式下导航栏状态全局唯一,切换页面仅替换Body内容,选中状态会同步更新。

方案二:路由跳转同步选中状态(适配必须用路由的场景)

如果坚持用路由跳转,需要让MyBottomNavBar知晓当前页面对应的索引,并在初始化时设置正确的_selectedIndex:

  1. 修改MyBottomNavBar,添加外部传参逻辑:
class MyBottomNavBar extends StatefulWidget {
  final int currentIndex; // 接收当前页面的索引
  final Function(int) onTap; // 点击回调

  const MyBottomNavBar({
    Key? key,
    required this.currentIndex,
    required this.onTap,
  }) : super(key: key);

  @override
  State<MyBottomNavBar> createState() => _MyBottomNavBarState();
}

class _MyBottomNavBarState extends State<MyBottomNavBar> {
  late int _selectedIndex;

  @override
  void initState() {
    super.initState();
    _selectedIndex = widget.currentIndex; // 初始化时同步外部传入的索引
  }

  @override
  void didUpdateWidget(covariant MyBottomNavBar oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 外部索引变化时同步更新
    if (oldWidget.currentIndex != widget.currentIndex) {
      setState(() {
        _selectedIndex = widget.currentIndex;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      backgroundColor: Colors.orangeAccent[100],
      currentIndex: _selectedIndex,
      onTap: widget.onTap,
      items: const [
        BottomNavigationBarItem(label: "Home", icon: Icon(Icons.home_filled)),
        BottomNavigationBarItem(label: "Play", icon: Icon(Icons.play_arrow_rounded)),
        BottomNavigationBarItem(label: "Create", icon: Icon(Icons.create)),
      ],
    );
  }
}
  1. 在各页面中使用时传入对应索引:
    例如MyHomePage:
class MyHomePage extends StatelessWidget {
  final String title;
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: const Center(child: Text("Home Page")),
      bottomNavigationBar: MyBottomNavBar(
        currentIndex: 0,
        onTap: (index) {
          if (index == 0) return; // 已在当前页面,无需跳转
          if (index == 1) {
            Navigator.pushNamed(context, "/play");
          } else if (index == 2) {
            Navigator.pushNamed(context, "/create");
          }
        },
      ),
    );
  }
}

Play页面:

class Play extends StatelessWidget {
  const Play({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Play")),
      body: const Center(child: Text("Play Page")),
      bottomNavigationBar: MyBottomNavBar(
        currentIndex: 1,
        onTap: (index) {
          if (index == 1) return;
          if (index == 0) {
            Navigator.pushNamed(context, "/home");
          } else if (index == 2) {
            Navigator.pushNamed(context, "/create");
          }
        },
      ),
    );
  }
}

这样每个页面的导航栏初始化时会设置正确的选中索引,解决显示不一致问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 21:50:39