Flutter如何自定义BottomNavigationBar底部导航栏选中项指示线位置?
解决方案
方案1:调整系统自带BottomNavigationBar的实现逻辑
你之前的写法错误原因是系统BottomNavigationBar默认的布局逻辑是icon在上、label在下,你把橙色条放在activeIcon的位置,自然会显示在文本上方。调整方法是直接自定义每个item的完整内容,不拆分使用icon和label属性:
// 选中状态的item组件 Widget _activeNavItem(String label) { return Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, children: [ Text( label, style: const TextStyle(color: Colors.white, fontSize: 14), ), const SizedBox(height: 4), Container( color: const Color(0xFFD86300), height: 5, width: 45, ) ], ); } // 未选中状态的item组件 Widget _inactiveNavItem(String label) { return Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, children: [ Text( label, style: const TextStyle(color: Colors.grey, fontSize: 14), ), const SizedBox(height: 9), // 未选中时用空白占位,保持所有item高度一致 ], ); } // BottomNavigationBarItem配置 BottomNavigationBarItem( icon: _inactiveNavItem('HOME'), activeIcon: _activeNavItem('HOME'), label: '', // label设空避免重复显示文本 )
配套BottomNavigationBar全局配置:
BottomNavigationBar( type: BottomNavigationBarType.fixed, selectedFontSize: 0, // 隐藏系统自带的label文本 unselectedFontSize: 0, // 隐藏系统自带的label文本 items: [ // 上面配置的BottomNavigationBarItem ], // 其他业务配置 )
方案2:完善你正在写的自定义底部导航栏
你当前的自定义代码结构已经是文本在上、指示条在下的正确布局,没有正常显示在下方的主要原因是没有给外层容器设置固定高度、也没有控制选中状态的指示条显隐,调整后的完整代码如下:
class CustomBottomNavigationBar extends StatefulWidget { final int currentIndex; final Function(int) onTap; const CustomBottomNavigationBar({super.key, required this.currentIndex, required this.onTap}); @override State<CustomBottomNavigationBar> createState() => _CustomBottomNavigationBarState(); } class _CustomBottomNavigationBarState extends State<CustomBottomNavigationBar> { final List<String> _labels = const ['HOME', 'CATEGORY', 'DISCOVER', 'CART', 'MINE']; @override Widget build(BuildContext context) { return Container( height: 60, // 给底部导航设置固定高度 color: const Color(0xFF393939), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate(_labels.length, (index) { final isSelected = index == widget.currentIndex; return InkWell( onTap: () => widget.onTap(index), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( _labels[index], style: TextStyle( color: isSelected ? Colors.white : Colors.grey, fontSize: 14 ), ), const SizedBox(height: 4), if(isSelected) Container( color: const Color(0xFFD86300), height: 5, width: 45, ) else const SizedBox(height: 5), // 未选中时占位保持高度一致 ], ), ); }), ), ); } } // 页面中调用示例 int _currentNavIndex = 0; @override Widget build(BuildContext context) { return Scaffold( key: _scaffoldKey, appBar: CustomTabletAppBar(_scaffoldKey), body: WebViewContainer('http://www.google.com'), bottomNavigationBar: CustomBottomNavigationBar( currentIndex: _currentNavIndex, onTap: (index) { setState(() { _currentNavIndex = index; }); // 补充页面切换的业务逻辑 }, ), ); }
内容的提问来源于stack exchange,提问作者satheesh ck
相关产品推荐
相关产品推荐

