Flutter 实战技巧:打造带渐变虚线边框的圆角组件

在日常开发中,为了提升视觉效果,我们经常需要给组件加上一些特殊的装饰性边框。今天就来教大家如何实现一个支持圆角、渐变色、虚线效果的容器边框组件。


🧩 功能概览

我们要做的组件具备以下特点:

  • ✅ 支持自定义圆角
  • ✅ 支持自定义虚线长度和间距
  • ✅ 支持线宽设置
  • ✅ 支持渐变色彩绘制

🛠 实现步骤详解

步骤 1:创建 CustomPainter

我们通过继承 CustomPainter 来实现绘图逻辑。核心在于使用 Canvas 绘制带有虚线效果的圆角矩形路径,并为其填充渐变色。

class _GradientDashedRRectPainter extends CustomPainter {
  final LinearGradient gradient;
  final double borderRadius;
  final double strokeWidth;
  final double dashLength;
  final double dashGap;

  const _GradientDashedRRectPainter({
    required this.gradient,
    required this.borderRadius,
    required this.strokeWidth,
    required this.dashLength,
    required this.dashGap,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final rect = Offset.zero & size;
    if (rect.isEmpty) return;

    final paint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..isAntiAlias = true
      ..shader = gradient.createShader(rect);

    final rrect = RRect.fromRectAndRadius(
        rect.deflate(strokeWidth / 2),
        Radius.circular(borderRadius));
    final path = Path()..addRRect(rrect);

    for (final metric in path.computeMetrics()) {
      double distance = 0;
      while (distance < metric.length) {
        final end = min(distance + dashLength, metric.length);
        canvas.drawPath(metric.extractPath(distance, end), paint);
        distance += dashLength + dashGap;
      }
    }
  }

  @override
  bool shouldRepaint(covariant _GradientDashedRRectPainter oldDelegate) {
    return oldDelegate.gradient != gradient ||
        oldDelegate.borderRadius != borderRadius ||
        oldDelegate.strokeWidth != strokeWidth ||
        oldDelegate.dashLength != dashLength ||
        oldDelegate.dashGap != dashGap;
  }
}

步骤 2:封装成可复用的 Widget

我们将上面的绘制类包装成一个通用的 DashedLineWidget 组件,方便在项目中反复使用。

class DashedLineWidget extends StatefulWidget {
  final Widget child;
  final double? borderRadius;
  final double? strokeWidth;
  final double? dashLength;
  final double? dashGap;
  final LinearGradient? gradient;

  const DashedLineWidget({
    super.key,
    required this.child,
    this.borderRadius,
    this.strokeWidth,
    this.dashLength,
    this.dashGap,
    this.gradient,
  });

  @override
  State<DashedLineWidget> createState() => _DashedLineWidgetState();
}

class _DashedLineWidgetState extends State<DashedLineWidget> {
  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _GradientDashedRRectPainter(
        gradient: widget.gradient ??
            const LinearGradient(
              colors: [Color(0xff3DEEFF), Color(0xffFF62F7)],
              begin: Alignment.centerLeft,
              end: Alignment.centerRight,
            ),
        borderRadius: widget.borderRadius ?? 0,
        strokeWidth: widget.strokeWidth ?? 1,
        dashLength: widget.dashLength ?? 5,
        dashGap: widget.dashGap ?? 3,
      ),
      child: Padding(
        padding: EdgeInsets.all(widget.strokeWidth ?? 1),
        child: widget.child,
      ),
    );
  }
}

📖 使用示例大全

示例 1:基础用法

最简单的使用方式,无需任何参数,使用默认的青色到粉色渐变:

DashedLineWidget(
  child: Container(
    width: 200,
    height: 100,
    alignment: Alignment.center,
    child: Text("默认虚线边框"),
  ),
)

效果:8像素圆角、1像素线宽、青粉渐变


示例 2:自定义圆角 + 线宽

想要更粗的边框和更大的圆角?调整参数即可:

DashedLineWidget(
  borderRadius: 20.0,    // 圆角20像素
  strokeWidth: 2.0,      // 线宽2像素
  child: Container(
    width: 200,
    height: 100,
    alignment: Alignment.center,
    child: Text("粗边框大圆角"),
  ),
)

示例 3:多彩渐变

从左到右的彩虹渐变效果:

DashedLineWidget(
  gradient: const LinearGradient(
    colors: [
      Colors.red,
      Colors.orange,
      Colors.yellow,
      Colors.green,
      Colors.blue,
      Colors.indigo,
      Colors.purple,
    ],
    begin: Alignment.centerLeft,
    end: Alignment.centerRight,
  ),
  borderRadius: 12.0,
  strokeWidth: 2.0,
  child: Container(
    width: 200,
    height: 100,
    alignment: Alignment.center,
    child: Text("彩虹渐变边框"),
  ),
)

示例 4:竖向渐变 + 短虚线

竖向渐变风格,配合更短的虚线段:

DashedLineWidget(
  gradient: const LinearGradient(
    colors: [Color(0xFF667eea), Color(0xFF764ba2)],
    begin: Alignment.topCenter,
    end: Alignment.bottomCenter,
  ),
  borderRadius: 8.0,
  dashLength: 4.0,   // 短虚线
  dashGap: 2.0,       // 紧凑间距
  child: Container(
    width: 200,
    height: 100,
    alignment: Alignment.center,
    child: Text("竖向渐变短虚线"),
  ),
)

示例 5:实用卡片场景

结合实际业务场景,作为卡片容器使用:

DashedLineWidget(
  borderRadius: 16.0,
  strokeWidth: 1.5,
  dashLength: 8.0,
  dashGap: 4.0,
  gradient: const LinearGradient(
    colors: [Color(0xFF00c6ff), Color(0xFF0072ff)],
    begin: Alignment.topLeft,
    end: Alignment.bottomRight,
  ),
  child: Card(
    elevation: 0,
    color: Color(0xFFF5F8FA),
    child: Padding(
      padding: EdgeInsets.all(16),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.star, color: Color(0xFF0072ff), size: 40),
          SizedBox(height: 8),
          Text("精选内容", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
          SizedBox(height: 4),
          Text("这是卡片内的描述文字", style: TextStyle(color: Colors.grey)),
        ],
      ),
    ),
  ),
)

💡 小结

通过本文介绍的方法,我们可以轻松地为任意组件添加美观的虚线渐变边框,具备以下高度可定制的参数:

参数 说明 默认值
borderRadius 圆角大小 8.0
strokeWidth 边框线宽 1.0
dashLength 虚线段长度 5.0
dashGap 虚线间距 3.0
gradient 渐变颜色 青→粉

非常适合用于卡片、按钮、弹窗、封面等 UI 场景中,能够有效提升界面的视觉层次感和设计感。

如果你觉得有用,欢迎分享给更多小伙伴! 🚀

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容