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

