There's no native API for drawing a dashed line in Flutter. An existing snippet allows drawing horizontal dashed lines but I can't find a snippet for drawing arbitrary dashed line from one point to another. There also exists a library called dash_painter that draws a dashed path. However, I'm only interested in drawing simple dashed lines. In particular, I'm looking for a snippet for drawing dashed lines that's similar to canvas.drawLine(Offset p1, Offset p2, Paint paint)
.
Asked
Active
Viewed 904 times
1

AlienKevin
- 2,691
- 2
- 17
- 19
-
2https://pub.dev/documentation/path_drawing/latest/path_drawing/dashPath.html - all you need to do is to call `moveTo` and `lineTo` on your `Path` - it should be faster than multiple calls to `Canvas.drawLine` – pskink Dec 25 '22 at 07:07
-
@pskink Thanks for pointing out the path_drawing library and the path commands. Since I'm only drawing a few dashed lines, I think the overhead of drawLine is not very pronounced. If you are interested, feel free to edit my answer to use path commands or provide your own alternative. – AlienKevin Dec 25 '22 at 16:37
1 Answers
2
Here's a function for drawing a dashed line from point p1 to point p2 in a CustomPainter
:
void drawDashedLine(
{required Canvas canvas,
required Offset p1,
required Offset p2,
required int dashWidth,
required int dashSpace,
required Paint paint}) {
// Get normalized distance vector from p1 to p2
var dx = p2.dx - p1.dx;
var dy = p2.dy - p1.dy;
final magnitude = sqrt(dx * dx + dy * dy);
dx = dx / magnitude;
dy = dy / magnitude;
// Compute number of dash segments
final steps = magnitude ~/ (dashWidth + dashSpace);
var startX = p1.dx;
var startY = p1.dy;
for (int i = 0; i < steps; i++) {
final endX = startX + dx * dashWidth;
final endY = startY + dy * dashWidth;
canvas.drawLine(Offset(startX, startY), Offset(endX, endY), paint);
startX += dx * (dashWidth + dashSpace);
startY += dy * (dashWidth + dashSpace);
}
}
Example usage: Draw a red dashed line from (0, 0) to (100, 100) with dash width of 6 and spacing of 4.
drawDashedLine(
canvas: canvas,
start: Offset(0, 0),
end: Offset(100, 100),
dashWidth: 6,
dashSpace: 4,
paint: Paint()..color = Colors.red..strokeWidth = 1);
EDIT
this is a version that uses one Canvas.drawPoints
method call:
void drawDashedLine({
required Canvas canvas,
required Offset p1,
required Offset p2,
required Iterable<double> pattern,
required Paint paint,
}) {
assert(pattern.length.isEven);
final distance = (p2 - p1).distance;
final normalizedPattern = pattern.map((width) => width / distance).toList();
final points = <Offset>[];
double t = 0;
int i = 0;
while (t < 1) {
points.add(Offset.lerp(p1, p2, t)!);
t += normalizedPattern[i++]; // dashWidth
points.add(Offset.lerp(p1, p2, t.clamp(0, 1))!);
t += normalizedPattern[i++]; // dashSpace
i %= normalizedPattern.length;
}
canvas.drawPoints(ui.PointMode.lines, points, paint);
}
in the most simple form you can call it with pattern: [20, 10]
but more complex patterns are possible: pattern: [20, 5, 5, 5]

pskink
- 23,874
- 6
- 66
- 77

AlienKevin
- 2,691
- 2
- 17
- 19
-
1your code does not draw the last segment correctly, see the updated method - try: `final p1 = Offset(100, 100); final p2 = Offset(300, 200); drawDashedLine(canvas: canvas, p1: p1, p2: p2, dashWidth: 20, dashSpace: 10, paint: p);` with your and my version and you will notice the difference on the last drawn segment, you can add `canvas.drawCircle(p2, 8, paint)` to better "see" the line end point – pskink Dec 25 '22 at 18:11
-
@pskink Your upated method looks fantastic. I wasn't aware of such functions like `Offset.lerp` and `Offset.distance` so I did the component math by hand. – AlienKevin Dec 28 '22 at 15:53
-
1indeed, a little bit like reinventing the wheel, now life is simpler :-) – pskink Dec 28 '22 at 16:02
-
btw `lerp` method is very handy and is used in many classes like `Rect.lerp`, `Size.lerp`, `Alignment.lerp`, `Color.lerp` and more than 100 other classes – pskink Dec 28 '22 at 17:25