如何在Flutter中设置选中状态BottomNavigationBarItem的背景色与尺寸
实现方案
原生BottomNavigationBar没有提供单独为选中项设置背景色、自定义尺寸的配置项,你可以选择以下两种方式实现需求:
方案1:基于现有组件改造,使用activeIcon自定义选中样式
给每个BottomNavigationBarItem配置activeIcon属性,传入带自定义背景、尺寸的组件即可,修改后的代码如下:
bottomNavigationBar: BottomNavigationBar( type: BottomNavigationBarType.fixed, backgroundColor: const Color(0xffffcc2a), showUnselectedLabels: true, currentIndex: _currentIndex, elevation: 20.0, onTap: callPage, selectedItemColor: const Color(0xff3666ad), unselectedItemColor: const Color(0xff3666ad), // 选中项的label文字样式可以单独调整尺寸 selectedLabelStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), unselectedLabelStyle: const TextStyle(fontSize: 12), items: [ BottomNavigationBarItem( // 未选中状态的图标 icon: const Icon( Icons.ballot, color: Color(0xff3666ad), ), // 选中状态的图标,外层包Container加背景、调整内边距控制尺寸 activeIcon: Container( width: 60, padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), decoration: BoxDecoration( color: Colors.white, // 这里替换为你要的选中项背景色 borderRadius: BorderRadius.circular(8), ), child: const Icon( Icons.ballot, color: Color(0xff3666ad), ), ), label: 'Insurance', ), BottomNavigationBarItem( icon: const FaIcon( FontAwesomeIcons.car, color: Color(0xff3666ad), ), activeIcon: Container( width: 60, padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: const FaIcon( FontAwesomeIcons.car, color: Color(0xff3666ad), ), ), label: 'Motor', ), // 剩下的4个item参照上面的格式修改activeIcon即可 BottomNavigationBarItem( icon: const Icon( Icons.medical_services, color: Color(0xff3666ad), ), activeIcon: Container( width: 60, padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: const Icon( Icons.medical_services, color: Color(0xff3666ad), ), ), label: 'Health', ), BottomNavigationBarItem( icon: const Icon( Icons.flight, color: Color(0xff3666ad), ), activeIcon: Container( width: 60, padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: const Icon( Icons.flight, color: Color(0xff3666ad), ), ), label: 'Travel', ), BottomNavigationBarItem( icon: const Icon( Icons.local_fire_department, color: Color(0xff3666ad), ), activeIcon: Container( width: 60, padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: const Icon( Icons.local_fire_department, color: Color(0xff3666ad), ), ), label: 'Fire', ), BottomNavigationBarItem( icon: const FaIcon( FontAwesomeIcons.layerGroup, color: Color(0xff3666ad), ), activeIcon: Container( width: 60, padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: const FaIcon( FontAwesomeIcons.layerGroup, color: Color(0xff3666ad), ), ), label: 'Misc', ) ], ),
这个方案改动最小,适合只需要修改选中图标周围背景的场景,如果需要选中项的背景铺满整个导航栏高度,建议用方案2。
方案2:完全自定义底部导航栏,灵活控制所有样式
直接抛弃原生BottomNavigationBar,自己用Row、GestureDetector组装底部导航,所有样式完全可控:
bottomNavigationBar: Container( height: 60, // 自定义整个导航栏高度 color: const Color(0xffffcc2a), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ // 第1个导航项 GestureDetector( onTap: () => callPage(0), child: Container( // 选中时填充整个导航栏高度,修改宽度、背景色 height: double.infinity, width: _currentIndex == 0 ? 70 : 60, color: _currentIndex == 0 ? Colors.white : Colors.transparent, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ Icon(Icons.ballot, color: Color(0xff3666ad)), Text('Insurance', style: TextStyle(color: Color(0xff3666ad), fontSize: 12),) ], ), ), ), // 第2个导航项 GestureDetector( onTap: () => callPage(1), child: Container( height: double.infinity, width: _currentIndex == 1 ? 70 : 60, color: _currentIndex == 1 ? Colors.white : Colors.transparent, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ FaIcon(FontAwesomeIcons.car, color: Color(0xff3666ad)), Text('Motor', style: TextStyle(color: Color(0xff3666ad), fontSize: 12),) ], ), ), ), // 剩下4个导航项参照上面的格式实现即可,下标对应2、3、4、5 ], ), ),
这个方案可以完全自定义选中项的尺寸、背景色、圆角、间距等所有样式,适配性最高。
内容的提问来源于stack exchange,提问作者Mari Selvan
相关产品推荐
相关产品推荐

