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

Flutter中如何让底部应用栏/导航栏边框仅覆盖选中项?

在Flutter中实现底部导航栏选中项专属顶部边框

方案一:自定义导航项实现

直接给每个导航项添加顶部边框,仅在选中时显示:

class CustomBottomNav extends StatefulWidget {
  const CustomBottomNav({super.key});

  @override
  State<CustomBottomNav> createState() => _CustomBottomNavState();
}

class _CustomBottomNavState extends State<CustomBottomNav> {
  int _selectedIndex = 0;
  final List<BottomNavigationBarItem> _navItems = [
    const BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
    const BottomNavigationBarItem(icon: Icon(Icons.search), label: "搜索"),
    const BottomNavigationBarItem(icon: Icon(Icons.person), label: "我的"),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex,
        onTap: (index) => setState(() => _selectedIndex = index),
        items: _navItems.asMap().entries.map((entry) {
          final index = entry.key;
          final item = entry.value;
          return BottomNavigationBarItem(
            icon: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                // 选中时显示顶部边框
                if (index == _selectedIndex)
                  Container(
                    height: 3,
                    width: 40,
                    color: Colors.blue, // 替换成你需要的边框颜色
                    margin: const EdgeInsets.only(bottom: 8),
                  ),
                item.icon!,
              ],
            ),
            label: item.label,
          );
        }).toList(),
        selectedItemColor: Colors.blue,
        unselectedItemColor: Colors.grey,
      ),
    );
  }
}

方案二:Stack叠加动态线条

不想修改每个导航项的话,用Stack将导航栏和定位线条组合:

class StackBottomNav extends StatefulWidget {
  const StackBottomNav({super.key});

  @override
  State<StackBottomNav> createState() => _StackBottomNavState();
}

class _StackBottomNavState extends State<StackBottomNav> {
  int _selectedIndex = 0;
  final List<Widget> _navItems = const [
    Icon(Icons.home),
    Icon(Icons.search),
    Icon(Icons.person),
  ];
  final List<String> _labels = ["首页", "搜索", "我的"];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: Stack(
        alignment: Alignment.topCenter,
        children: [
          // 基础底部导航栏
          BottomNavigationBar(
            currentIndex: _selectedIndex,
            onTap: (index) => setState(() => _selectedIndex = index),
            items: _navItems
                .asMap()
                .entries
                .map((entry) => BottomNavigationBarItem(
                      icon: entry.value,
                      label: _labels[entry.key],
                    ))
                .toList(),
            selectedItemColor: Colors.blue,
            unselectedItemColor: Colors.grey,
          ),
          // 随选中项移动的顶部边框
          Positioned(
            left: MediaQuery.of(context).size.width / _navItems.length * _selectedIndex +
                (MediaQuery.of(context).size.width / _navItems.length - 40) / 2,
            top: 0,
            child: Container(
              height: 3,
              width: 40,
              color: Colors.blue,
            ),
          ),
        ],
      ),
    );
  }
}

小提示

  • 方案一灵活度高,能给选中项添加更多自定义样式(比如圆角边框、渐变颜色)
  • 方案二的线条独立于导航项,适合需要统一控制线条位置和样式的场景
  • 调整Container的height、width、color就能匹配你的设计图

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:35:39