You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Flutter中BottomNavigationBarItem选中项的label添加线性渐变

实现BottomNavigationBar选中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 13:39:01