Flutter provides many standard components that we can use in our projects, but we often need to customize our own views. The most common and basic way to customize a View is to use Path.

Let’s start learning Path in earnest.

First, preliminary preparation

Let’s start with a piece of code.

import 'package:flutter/material.dart';

void main() => runApp(
      MaterialApp(
        home: PathExample(),
      ),
    );

class PathExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    returnCustomPaint( painter: PathPainter(), ); } } class PathPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; Path path = Path(); // TODO:do operations here
    path.close();
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}
Copy the code

In the above code, our home page is a component of type StatelessWidget. In the build method, we return the CustomPaint Widget. The painter that CustomPaint needs to use is our customized PathPainter. The CustomPaint component provides us with a canvas on which we can use our custom CustomPainter to draw the content specified in paint().

For draw-related options, we can set them using the Paint component, including color, style, brush thickness, and so on.

Paint paint = Paint() .. Color = Colors. BlueAccent // paint color.. StrokeCap = strokecap. round // Brush stroke type.. isAntiAlias =true// Whether to enable anti-aliasing.. BlendMode = blendmode. exclusion // Color blending mode.. Style = paintingstyle. fill // default to fill.. ColorFilter = colorfilter.mode (color.blueaccent, blendmode.exclusion) // Color rendering mode.. MaskFilter = maskfilter.blur (blurstyle.inner, 3.0) FilterQuality = filterQuality. High // Color render mode quality.. StrokeWidth = 5.0; // The brush widthCopy the code

Now we can define a Path object to decide what to draw. The Path object is a collection of elements that need to be drawn from a starting point (the default Path starting point is (0,0)).

Finally, we need to use the Canvas drawPath method to draw the path. This method takes two parameters: path and paint.

That’s pretty much the basic flow of drawing with Path. For the coordinate system on the phone, as shown below, the upper left corner is the origin of the coordinates.

Second, the moveTo

The moveTo method moves the seven points drawn to the specified position.

@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; Path path = Path(); // Move the starting point to the center of the screen. Path.moveto (sie.width / 2, sie.height / 2); canvas.drawPath(path, paint); }Copy the code

Three, lineTo,

The lineTo method draws a line from the starting point to a point specified in the lineTo.

@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; Path path = Path(); // From the top left to the bottom right end path.lineTo(sie.width, sie.height); canvas.drawPath(path, paint); }Copy the code

Four, quadraticBezierTo

QuadraticBezierTo is what plots second-order bezier curves.

As can be seen from the figure above, three points are needed to draw a Bezier curve: a starting point, a control point, and an end point.

@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; Path path = Path(); path.moveTo(0, size.height / 2); path.quadraticBezierTo(size.width / 2, size.height, size.width, size.height / 2); canvas.drawPath(path, paint); }Copy the code

Fifth, cubicTo

CubicTo is used to plot third-order Bessel curves.

A third-order Bessel requires two control points.

@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; Path path = Path(); path.cubicTo(size.width / 4, 3 * size.height / 4, 3 * size.width / 4, size.height / 4, size.width, size.height); canvas.drawPath(path, paint); }Copy the code

Six, conicTo

The conicTo method is similar to the quadraticBeizerTo method, but it is mainly controlled by the weight parameter. When weight is greater than 1, you plot a hyperbola, when weight is equal to 1, you plot a parabola, and when weight is less than 1, you plot an ellipse.

@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; Path path = Path(); path.conicTo(size.width / 4, 3 * size.height / 4, size.width, size.height, 20); canvas.drawPath(path, paint); }Copy the code

Seven, arcTo

ArcTo method is to draw arcs, and the method prototype is as follows:

void arcTo(Rect rect, double startAngle, double sweepAngle, bool forceMoveTo)
Copy the code

Four parameters are required:

  • Rect: the rectangle where the arc is
  • StartAngle: indicates the starting radian
  • SweepAngle: The number of radians to draw
  • ForceMoveTo: If the ‘forceMoveTo’ parameter is false, a straight line and an arc are added. If the “forceMoveTo” parameter is true, a new subpath containing an arc is started.
@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; // Method to convert degree to radians num degToRad(num deg) => deg * (math.pi / 180.0); Path path = Path(); path.arcTo(Rect.fromLTWH(size.width / 2, size.height / 2, size.width / 4, size.height / 4), degToRad(0), degToRad(90),true);
    canvas.drawPath(path, paint);
  }
Copy the code

Eight, addRect

Draw a rectangle.

@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; Path path = Path(); // Adds a rectangle path.addRect(Rect.fromLTWH(size.width / 2, size.height / 2, size.width / 4, size.height / 4)); canvas.drawPath(path, paint); }Copy the code

Nine, addOval

Draw the ellipse.

@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; Path path = Path(); // Adds an oval path.addOval(Rect.fromLTWH(size.width / 2, size.height / 2, size.width / 4, size.height / 4)); canvas.drawPath(path, paint); }Copy the code

Ten, addArc

Drawing arcs is similar to arcTo

@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; // Method to convert degree to radians num degToRad(num deg) => deg * (math.pi / 180.0); Path path = Path(); // Adds a quarter arc path.addArc(Rect.fromLTWH(0, 0, size.width, size.height), degToRad(180), degToRad(90)); canvas.drawPath(path, paint); }Copy the code

Eleven, addPolygon

Draw polygons. You can specify the vertices of a polygon, and when the last argument is true, the last and first points are joined, the polygon is closed, and when false, it is not closed.

@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; Path path = Path(); // Adds a polygon from the starting point to quarter point of the screen and lastly // it will bein the bottom middle. Close method will draw a line between start and end.
   path.addPolygon([
     Offset.zero,
     Offset(size.width / 4, size.height / 4),
     Offset(size.width / 2, size.height)
   ], false);
   canvas.drawPath(path, paint);
 }
Copy the code
  • false

  • true

Twelve, addRRect

Draws a rounded rectangle whose radian is controlled by the last parameter.

@override void paint(Canvas canvas, Size size) { Paint paint = Paint() .. color = Colors.red .. style = PaintingStyle.stroke .. StrokeWidth = 8.0; Path path = Path(); path.addRRect( RRect.fromRectAndRadius(Rect.fromLTWH(size.width / 2, size.height / 2, size.width / 4, size.height / 4), Radius.circular(16)) ); canvas.drawPath(path, paint); }Copy the code

Path practice drawing progress bar

Class CircleProgressBarPainter extends CustomPainter {// background Paint _paintBackground; // foreground Paint _foreground; var currentValue; CircleProgressBarPainter(this.currentValue) { _paintBackground = Paint() .. color = Colors.blue .. strokeCap = StrokeCap.round .. style = PaintingStyle.stroke .. StrokeWidth = 10.0.. isAntiAlias =true; _paintForeground = Paint() .. color = Colors.red .. strokeCap = StrokeCap.round .. style = PaintingStyle.stroke .. StrokeWidth = 10.0.. isAntiAlias =true; } override void paint(Canvas Canvas, Size Size) {Canvas. DrawCircle (Offset(size.width / 2, size.height / 2), size.width / 2, _paintBackground); Rect rect = Rect.fromCircle( center: Offset(size.width / 2, size.height / 2), radius: size.width / 2, ); // Canvas. DrawArc (rect, 0.0, currentValue * math.pi / 180,false, _paintForeground);
 }



 @override
 bool shouldRepaint(CustomPainter oldDelegate) {
   return false; }}Copy the code

use


   returnContainer( width: width, height: height, padding: EdgeInsets.all(20), child: CustomPaint( child: Center( child: Text((progressanimation.value / 3.6).round().tostring (), style: TextStyle(fontSize: 24,color: RGB (51, 51, 51)) Colors.blue), ), ), painter: CircleProgressBarPainter(progressAnimation.value) ), );Copy the code

Effect:

Reference: medium.com/flutter-com…


github