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

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

  • Paint style will be customizable. User will be able to define its own paint style.
  • Dot size and gap size between dots will be customizable.
  • And most importantly, the line will be symmetric with respect to the midpoint of line for any size.

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

If you interested in zigzag line, please read this article Flutter — paint zigzagline (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 dotted. Our focus will be on dotted 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 DottedLine extends Line {
final double gapSize;

DottedLine({this.gapSize});
}

Let’s design our line painter class — Line painter will take line definition (which is solid or dotted) 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();

Row lineWrapper = Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
height: paint.strokeWidth,
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 dotted line outputs:

Column(
children: [
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 240,
child: AdvancedLine(
direction: Axis.horizontal,
line: DottedLine(),
),
),
],
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 240,
height: 9.0,
color: Colors.yellow,
alignment: Alignment.center,
child: AdvancedLine(
direction: Axis.horizontal,
line: DottedLine(),
paintDef: Paint()..strokeWidth = 3.0,
),
),
],
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 240,
height: 9.0,
color: Colors.yellow,
alignment: Alignment.center,
child: AdvancedLine(
direction: Axis.horizontal,
line: DottedLine(),
paintDef: Paint()
..strokeWidth = 3.0
..strokeCap = StrokeCap.round,
),
),
],
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 12,
height: 160,
color: Colors.yellow,
alignment: Alignment.center,
child: AdvancedLine(
direction: Axis.vertical,
line: DottedLine(),
paintDef: Paint()
..strokeWidth = 3.0
..strokeCap = StrokeCap.square,
),
),
],
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: AdvancedLine(
direction: Axis.horizontal,
line: DottedLine(gapSize: 5.0),
paintDef: Paint()
..strokeWidth = 3.0
..strokeCap = StrokeCap.round
..color = Colors.black54,
),
),
],
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: AdvancedLine(
direction: Axis.horizontal,
line: DottedLine(gapSize: 5.0),
paintDef: Paint()
..strokeWidth = 8.0
..strokeCap = StrokeCap.round
..color = Colors.black54,
),
),
],
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: AdvancedLine(
direction: Axis.horizontal,
line: DottedLine(gapSize: 3.0),
paintDef: Paint()
..strokeWidth = 20.0
..strokeCap = StrokeCap.round
..color = Colors.black54,
),
),
],
),
],
),

We can provide symmetry with a very simple calculation method.

Best regards.

Java, Flutter — Dart Software Developer