Flutter — paint zigzag line (both horizontal and vertical axis)

Lets create a widget that rendering horizontal or vertical zigzag line having these features:

  • Paint style will be customizable. User will be able to define its own paint style.
  • Zigzag depth (height) and angle will be customizable

If you interested in dashed line (symmetric formulated), please read this article Flutter — paint dashed line (both horizontal and vertical axis)

Let’s start designing an abstract line class, we will extend line pattern classes from this class:

abstract class Line {}

Now, let’s extend two line pattern class: solid and zigzag. Our focus will be on zigzag line, but in some cases we will use solid line painter which with more performance (always escape from unnecessary calculation).

class SolidLine extends Line {}class ZigzagLine extends Line {
final double depth;
final double angle;

ZigzagLine({this.depth, this.angle});
}

Let’s design our line painter class — Line painter will take line definition (which is solid or zigzag) and the paint style as parameter to produce the requested line.

Let’s design our AdvancedLine widget. Please notice that, our line painter class rendering only horizontal lines, if user requests vertical line, AdvancedLine widget will rotate the rendered horizontal line 90 degrees.

class AdvancedLine extends StatelessWidget {
final Axis direction;
final Line line;
final Paint paintDef;

const AdvancedLine({
Key key,
@required this.direction,
@required this.line,
this.paintDef,
}) : super(key: key);

@override
Widget build(BuildContext context) {
// line painter, always rendering horizontal line
// if requested axis is vertical
// send horizontal line with 90 degree rotated

Paint paint = this.paintDef ?? Paint();
double spaceDepth = paint.strokeWidth;

if (line is ZigzagLine) spaceDepth = (line as ZigzagLine).depth ?? 8.0;

Row lineWrapper = Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
height: spaceDepth,
child: CustomPaint(
painter: LinePainter(line: line, paintDef: paint),
),
),
),
],
);

if (direction == Axis.horizontal)
return lineWrapper;
else
return new
RotatedBox(
quarterTurns: 1,
child: lineWrapper,
);
}
}

Let’s build some zigzag line outputs:

Column(
children: [
SizedBox(height: 25.0),
Row(
children: [
Expanded(
child: AdvancedLine(
direction: Axis.horizontal,
line: ZigzagLine(angle: 60, depth: 8.0),
paintDef: Paint()
..strokeWidth = 1.0
..style = PaintingStyle.stroke,
),
),
],
),
SizedBox(height: 25.0),
Row(
children: [
Expanded(
child: AdvancedLine(
direction: Axis.horizontal,
line: ZigzagLine(angle: 90, depth: 20.0),
paintDef: Paint()..strokeWidth = 1.0),
),
],
),
SizedBox(height: 25.0),
Row(
children: [
Container(
width: 240,
height: 16.0,
color: Colors.deepOrangeAccent,
child: AdvancedLine(
direction: Axis.horizontal,
line: ZigzagLine(angle: 90, depth: 16.0),
paintDef: Paint()
..strokeWidth = 2.0
..style = PaintingStyle.stroke,
),
),
],
),
SizedBox(height: 25.0),
Row(
children: [
Container(
width: 240,
height: 48.0,
color: Colors.lightBlueAccent,
child: AdvancedLine(
direction: Axis.horizontal,
line: ZigzagLine(angle: 45, depth: 16.0),
paintDef: Paint()
..strokeWidth = 2.0
..style = PaintingStyle.stroke,
),
),
],
),
SizedBox(height: 25.0),
Row(
children: [
Container(
width: 320,
height: 60.0,
alignment: Alignment.center,
color: Colors.lightBlueAccent,
child: AdvancedLine(
direction: Axis.horizontal,
line: ZigzagLine(angle: 45, depth: 16.0),
paintDef: Paint()
..strokeWidth = 3.0
..style = PaintingStyle.stroke,
),
),
],
),
],
),
  • The first zigzag line defined inside an Expanded Container.
  • The second zigzag line defined (inside Expanded) with default paint style which is ‘PaintingStyle.fill’. See the difference.
  • See the difference between third and fourth zigzag line, zigzag depth and thickness (stroke width) are equal but the angle is not.

Let’s build a vertical zigzag line:

Column(
children: [
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 240,
height: 16.0,
color: Colors.deepOrangeAccent,
child: AdvancedLine(
direction: Axis.horizontal,
line: ZigzagLine(angle: 90, depth: 16.0),
paintDef: Paint()
..strokeWidth = 2.0
..style = PaintingStyle.stroke,
),
),
],
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 24,
height: 240,
color: Colors.lightBlueAccent,
alignment: Alignment.center,
child: AdvancedLine(
direction: Axis.vertical,
line: ZigzagLine(angle: 45, depth: 16.0),
paintDef: Paint()
..strokeWidth = 2.0
..style = PaintingStyle.stroke,
),
),
],
)
],
),

If you wondering how calculating the zigzag aperture (zigzag width), please see image below.

Best regards…

Java, Flutter — Dart Software Developer