[Flutter] 如何绘制一条虚线,支持横竖、支持Expand 的长度

431 阅读1分钟

题记

只是一个很简单的绘制虚线的需求,发现前同事写的一个组件,他得方案是通过LayoutBuilder 获取的宽高、然后循环绘制 SizeBox 然后设置背景色...

这个方案,怎么说吧,遇到不定宽高的虚线时,就不好使用了,左侧的虚线是根据右侧项目的高度变化的。

如下图:

image.png

所以需要一个可以根据容器情况来绘制的虚线。

我这边推荐的是使用 CustomPainter 通过自定义画笔,可以很好的拿到组件的宽高,然后直接绘制一条虚线即可.

需要注意的是:代码中 CustomPainter内使用Container而不是SizeBox是因为, 如果外层套着 Expand的话SizeBox不会生效的。

完整代码


import 'package:flutter/material.dart';
import 'package:sales_point/const/const_color.dart';

///绘制虚线
class DashLine extends StatelessWidget {
  final Color color;
  final bool isHorizontal;
  final double gap;
  final double lineWidth;
  final double? width;
  final double? height;

  const DashLine.horizontal({
    super.key,
    this.color = ConstColor.colorEBEBEB,
    this.gap = 4,
    this.lineWidth = 5,
    this.width,
    this.height = 2,
  }) : isHorizontal = true;

  const DashLine.vertical({
    super.key,
    this.color = ConstColor.colorEBEBEB,
    this.gap = 4,
    this.lineWidth = 5,
    this.width = 2,
    this.height,
  }) : isHorizontal = false;

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      foregroundPainter: DashLinePainter(
        color: color,
        isHorizontal: isHorizontal,
        lineWidth: lineWidth,
        gap: gap,
      ),
      child: Container(
        width: width,
        height: height,
      ),
    );
  }
}

/// 为卡片画上一个线条
class DashLinePainter extends CustomPainter {
  final Color color;
  final bool isHorizontal;
  final double gap;
  final double lineWidth;

  DashLinePainter({
    super.repaint,
    required this.color,
    this.isHorizontal = false,
    this.gap = 2,
    this.lineWidth = 5,
  });

  @override
  void paint(Canvas canvas, Size size) {
    // 创建一个画笔对象,设置颜色和线宽
    final drawWidth = isHorizontal ? size.height : size.width;
    Paint paint = Paint()
      ..color = color
      ..strokeWidth = drawWidth
      ..style = PaintingStyle.stroke;

    // 使用画笔和定义的起点、终点来绘制线条
    final x = drawWidth / 2;
    if (isHorizontal) {
      for (var i = 0.0; i < size.width; i += (lineWidth + gap)) {
        final startPosition = Offset(i, x);
        final endPosition = Offset(i + lineWidth, x);
        canvas.drawLine(startPosition, endPosition, paint);
      }
    } else {
      for (var i = 0.0; i < size.height; i += (lineWidth + gap)) {
        final startPosition = Offset(x, i);
        final endPosition = Offset(x, i + lineWidth);
        canvas.drawLine(startPosition, endPosition, paint);
      }
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

Bye~