如何为Flutter中BottomNavigationBarItem选中项的label添加线性渐变
原生BottomNavigationBar的label仅支持传入字符串,默认无法直接设置渐变效果,可通过以下两种方案实现:
方案1:自定义activeIcon整合渐变文字(推荐)
该方案灵活度最高,适配所有文字长度,渐变效果和图标完全一致。
第一步:实现通用渐变文本组件
class GradientText extends StatelessWidget { final String text; final Gradient gradient; final TextStyle? style; const GradientText({ super.key, required this.text, required this.gradient, this.style, }); @override Widget build(BuildContext context) { return ShaderMask( blendMode: BlendMode.srcIn, shaderCallback: (bounds) => gradient.createShader( Rect.fromLTWH(0, 0, bounds.width, bounds.height), ), child: Text(text, style: style), ); } }
第二步:修改底部导航栏配置
- 给BottomNavigationBar添加
showSelectedLabels: false属性,隐藏选中状态下的默认label - 改造每个BottomNavigationBarItem的activeIcon,将渐变图标和渐变文字整合到Column中
修改后的完整代码如下:
BottomNavigationBar( onTap: onTabTapped, currentIndex: _currentPage, backgroundColor: context.appTheme.primaryBackgroundColor, type: BottomNavigationBarType.fixed, unselectedItemColor: context.appTheme.primaryTextColor, showUnselectedLabels: true, showSelectedLabels: false, // 新增:隐藏选中状态默认label items: [ BottomNavigationBarItem( activeIcon: Column( mainAxisSize: MainAxisSize.min, children: [ GradientMask( child: Icon(Icons.home_filled), gradient: context.appTheme.primaryGradient, ), SizedBox(height: 4), // 调整图标文字间距,匹配原生导航栏样式 GradientText( 'Home', gradient: context.appTheme.primaryGradient, style: TextStyle(fontSize: 12), ) ], ), icon: Icon(Icons.home_filled), label: 'Home', ), BottomNavigationBarItem( activeIcon: Column( mainAxisSize: MainAxisSize.min, children: [ GradientMask( child: Icon(Icons.search), gradient: context.appTheme.primaryGradient, ), SizedBox(height: 4), GradientText( 'Search', gradient: context.appTheme.primaryGradient, style: TextStyle(fontSize: 12), ) ], ), icon: Icon(Icons.search), label: 'Search', ), BottomNavigationBarItem( activeIcon: Column( mainAxisSize: MainAxisSize.min, children: [ GradientMask( child: Icon(Icons.savings), gradient: context.appTheme.primaryGradient, ), SizedBox(height: 4), GradientText( 'Earnings', gradient: context.appTheme.primaryGradient, style: TextStyle(fontSize: 12), ) ], ), icon: Icon(Icons.savings), label: 'Earnings' ), BottomNavigationBarItem( activeIcon: Column( mainAxisSize: MainAxisSize.min, children: [ GradientMask( child: Icon(Icons.volunteer_activism), gradient: context.appTheme.primaryGradient, ), SizedBox(height: 4), GradientText( 'Sharing', gradient: context.appTheme.primaryGradient, style: TextStyle(fontSize: 12), ) ], ), icon: Icon(Icons.volunteer_activism), label: 'Sharing' ), BottomNavigationBarItem( activeIcon: Column( mainAxisSize: MainAxisSize.min, children: [ GradientMask( child: Icon(Icons.inventory_2), gradient: context.appTheme.primaryGradient, ), SizedBox(height: 4), GradientText( 'My Items', gradient: context.appTheme.primaryGradient, style: TextStyle(fontSize: 12), ) ], ), icon: Icon(Icons.inventory_2), label: 'My Items' ) ], ),
方案2:通过TextStyle的foreground属性实现
如果不想修改item结构,可以直接在selectedLabelStyle中设置渐变Paint,缺点是需要手动适配文字尺寸,不同长度的文字渐变效果可能不一致:
BottomNavigationBar( // 其余原有属性保持不变 selectedLabelStyle: TextStyle( fontSize: 12, foreground: Paint() ..shader = context.appTheme.primaryGradient.createShader( // 矩形尺寸根据你的label最大长度调整 Rect.fromLTWH(0, 0, 80, 20), ) ), )
内容的提问来源于stack exchange,提问作者Tonnanto
相关产品推荐
相关产品推荐

