如何为Flutter中BottomNavigationBar的selectedItemColor添加渐变效果
原生的BottomNavigationBar的selectedItemColor属性不支持直接设置渐变效果,我们可以通过自定义选中状态下的图标和文字来实现这个需求。核心思路是用ShaderMask包裹图标和文本,为其添加渐变着色,然后根据当前选中的索引来切换显示普通样式还是渐变样式。
实现步骤与代码示例
封装带渐变的可复用组件
先写一个通用组件,用来生成带渐变效果的图标和文字:class GradientIconText extends StatelessWidget { final IconData icon; final String label; final Gradient gradient; const GradientIconText({ super.key, required this.icon, required this.label, required this.gradient, }); @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ ShaderMask( shaderCallback: (bounds) => gradient.createShader( Rect.fromLTWH(0, 0, bounds.width, bounds.height), ), child: Icon(icon, color: Colors.white), ), const SizedBox(height: 4), ShaderMask( shaderCallback: (bounds) => gradient.createShader( Rect.fromLTWH(0, 0, bounds.width, bounds.height), ), child: Text(label, style: const TextStyle(color: Colors.white)), ), ], ); } }改造BottomNavigationBar实现
维护当前选中索引,根据状态切换显示渐变组件或普通组件:class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _selectedIndex = 0; // 自定义渐变样式,可按需修改颜色和方向 final Gradient _selectedGradient = const LinearGradient( colors: [Colors.blue, Colors.purple], begin: Alignment.topLeft, end: Alignment.bottomRight, ); void _onItemTapped(int index) { setState(() { _selectedIndex = index; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('渐变底部导航')), body: const Center(child: Text('首页内容')), bottomNavigationBar: BottomNavigationBar( currentIndex: _selectedIndex, onTap: _onItemTapped, showUnselectedLabels: true, unselectedItemColor: Theme.of(context).colorScheme.onBackground, items: [ BottomNavigationBarItem( icon: _selectedIndex == 0 ? GradientIconText( icon: Icons.home, label: 'Home', gradient: _selectedGradient, ) : const Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.home), SizedBox(height: 4), Text('Home'), ], ), label: '', // 自定义组件已包含文字,此处留空避免重复 ), BottomNavigationBarItem( icon: _selectedIndex == 1 ? GradientIconText( icon: Icons.favorite, label: 'Favorite', gradient: _selectedGradient, ) : const Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.favorite), SizedBox(height: 4), Text('Favorite'), ], ), label: '', ), BottomNavigationBarItem( icon: _selectedIndex == 2 ? GradientIconText( icon: Icons.settings, label: 'Setting', gradient: _selectedGradient, ) : const Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.settings), SizedBox(height: 4), Text('Setting'), ], ), label: '', ), BottomNavigationBarItem( icon: _selectedIndex == 3 ? GradientIconText( icon: Icons.abc, label: 'idk', gradient: _selectedGradient, ) : const Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.abc), SizedBox(height: 4), Text('idk'), ], ), label: '', ), ], ), ); } }
关键说明
ShaderMask是实现渐变着色的核心,它通过shaderCallback生成渐变着色器,将子组件的颜色替换为渐变效果。- 因为自定义组件已经包含了文字,所以
BottomNavigationBarItem的label需要设为空字符串,避免重复显示文字。 - 你可以直接修改
_selectedGradient的颜色数组和对齐方式,快速切换不同的渐变风格。
内容的提问来源于stack exchange,提问作者Mohamad Bdeir
相关产品推荐
相关产品推荐

