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

Flutter TabBar自定义渐变边框+渐变背景Indicator实现求助

实现带渐变边框+渐变背景的TabBar自定义Indicator

由于Flutter的BoxDecoration无法直接实现渐变边框(Border.all仅支持纯色),你需要自定义一个Decoration来实现需求。以下是完整的可行方案:

1. 自定义渐变边框Indicator类

创建继承自Decoration的类,通过重写paint方法分别绘制渐变边框和渐变背景:

class GradientBorderIndicator extends Decoration {
  final double borderWidth;
  final BorderRadius borderRadius;
  final Gradient borderGradient;
  final Gradient backgroundGradient;

  const GradientBorderIndicator({
    this.borderWidth = 2.0,
    this.borderRadius = const BorderRadius.all(Radius.circular(16)),
    required this.borderGradient,
    required this.backgroundGradient,
  });

  @override
  BoxPainter createBoxPainter([VoidCallback? onChanged]) {
    return _GradientBorderPainter(
      borderWidth: borderWidth,
      borderRadius: borderRadius,
      borderGradient: borderGradient,
      backgroundGradient: backgroundGradient,
    );
  }
}

class _GradientBorderPainter extends BoxPainter {
  final double borderWidth;
  final BorderRadius borderRadius;
  final Gradient borderGradient;
  final Gradient backgroundGradient;

  _GradientBorderPainter({
    required this.borderWidth,
    required this.borderRadius,
    required this.borderGradient,
    required this.backgroundGradient,
  });

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    final Rect rect = offset & configuration.size!;
    // 计算内部背景矩形(减去边框宽度)
    final Rect innerRect = rect.deflate(borderWidth);
    // 边框的圆角路径
    final RRect borderRRect = borderRadius.toRRect(rect);
    // 内部背景的圆角路径(半径减去边框宽度)
    final RRect innerRRect = borderRadius.subtract(BorderRadius.circular(borderWidth)).toRRect(innerRect);

    // 绘制渐变边框
    final Paint borderPaint = Paint()
      ..shader = borderGradient.createShader(rect)
      ..style = PaintingStyle.stroke
      ..strokeWidth = borderWidth;
    canvas.drawRRect(borderRRect, borderPaint);

    // 绘制渐变背景
    final Paint backgroundPaint = Paint()
      ..shader = backgroundGradient.createShader(innerRect);
    canvas.drawRRect(innerRRect, backgroundPaint);
  }
}

2. 在TabBar中使用自定义Indicator

修改原有代码,替换BoxDecoration为自定义的GradientBorderIndicator:

@override
Widget build(BuildContext context) {
  List<String> list = ["全部","读书","电影", "小说"];

  // 定义边框渐变和背景渐变
  final borderGradient = LinearGradient(
    colors: [
      Color(0xFF08FFFB),
      Color(0xFFFF4EEC),
    ],
  );

  final backgroundGradient = LinearGradient(
    begin: Alignment.topCenter,
    end: Alignment.bottomCenter,
    colors: [
      Color(0xFF3A3A3A),
      Color(0xFF0B0B0B),
    ],
  );

  return Padding(
    padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
    child: Container(
      width: double.infinity,
      height: 62,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.all(Radius.circular(20))
      ),
      child: Padding(
        padding: EdgeInsets.fromLTRB(25, 13, 25, 13),
        child: TabBar(
          labelColor: Colors.white,
          unselectedLabelColor: YYSColors.yysTextColor(),
          isScrollable: true,
          // 使用自定义Indicator
          indicator: GradientBorderIndicator(
            borderWidth: 2,
            borderRadius: BorderRadius.circular(16),
            borderGradient: borderGradient,
            backgroundGradient: backgroundGradient,
          ),
          tabs: list
              .map((String arenaType) {
            return Tab(text: arenaType);
          }).toList(),
        ),
      ),
    ),
  );
}

关键说明

  • 自定义Indicator通过两次绘制实现:先画渐变边框(PaintingStyle.stroke),再画内部渐变背景(默认PaintingStyle.fill)。
  • 内部背景的圆角半径需减去边框宽度,避免背景超出边框导致圆角显示异常。
  • 直接用Color(0xFFxxxxxx)语法替代int.parse,代码更简洁高效。

内容的提问来源于stack exchange,提问作者Wilson Tang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 05:25:52