Flutter中如果想要自定義繪制丢郊,那么你需要用到 CustomPaint 和 CustomPainter ; CustomPaint是Widget的子類。
const CustomPaint({
Key key,
this.painter,
this.foregroundPainter,
this.size = Size.zero,
this.isComplex = false,
this.willChange = false,
Widget child,
}) :super(key: key, child: child);
示例
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Painter繪制直線'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: CustomPaint(
size: Size(300, 300),
painter:MyPainter() ,
),
)
);
}
}
class MyPainter extends CustomPainter {
///[定義畫筆]
Paint _paint = Paint()
..color = Colors.blueAccent //畫筆顏色
..strokeCap = StrokeCap.round//畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒
..style = PaintingStyle.fill //繪畫風格棚放,默認為填充
..strokeWidth = 5.0; //畫筆的寬度
@override
void paint(Canvas canvas, Size size) {
canvas.drawLine(Offset(20, 20), Offset(100,100), _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return null;
}
}
定義畫筆
///[定義畫筆]
Paint _paint = Paint()
..color = Colors.blueAccent //畫筆顏色
..strokeCap = StrokeCap.round//畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒
..style = PaintingStyle.fill //繪畫風格家乘,默認為填充
..strokeWidth = 5.0; //畫筆的寬度
繪制直線(drawLine)
使用給定的涂料在給定點之間繪制一條線娜汁。 該行被描邊党晋,此調(diào)用忽略[Paint.style]的值寻咒。p1和p2參數(shù)為兩個點的坐標 , 在這兩點之間繪制一條直線哮翘。
class MyPainter extends CustomPainter {
///[定義畫筆]
Paint _paint = Paint()
..color = Colors.blueAccent //畫筆顏色
..strokeCap = StrokeCap.round//畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒
..style = PaintingStyle.fill //繪畫風格,默認為填充
..strokeWidth = 5.0; //畫筆的寬度
@override
void paint(Canvas canvas, Size size) {
canvas.drawLine(Offset(20, 20), Offset(100,100), _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return null;
}
}
繪制點(drawPoints)
繪制點也是非常的簡單毛秘,3個參數(shù)分別為: PointMode枚舉饭寺,坐標 list 和 paint。PointMode的枚舉類型有三個叫挟,points(點)艰匙,lines(線,隔點連接)抹恳,polygon(線员凝,相鄰連接)
void drawPoints(PointMode pointMode, List points, Paint paint)
class MyPainter extends CustomPainter {
///[定義畫筆]
Paint _paint = Paint()
..color = Colors.blueAccent //畫筆顏色
..strokeCap = StrokeCap.round//畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒
..style = PaintingStyle.fill //繪畫風格,默認為填充
..strokeWidth = 5.0; //畫筆的寬度
@override
void paint(Canvas canvas, Size size) {
///PointMode的枚舉類型有三個奋献,points(點)健霹,lines(線,隔點連接)瓶蚂,polygon(線糖埋,相鄰連接)
canvas.drawPoints(
PointMode.points,
[
Offset(20.0, 40.0),
Offset(100.0, 120.0),
Offset(100.0, 220.0),
Offset(200.0, 220.0),
Offset(200.0, 120.0),
Offset(280.0, 40.0),
Offset(20, 40.0),
],
_paint
);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return null;
}
}
PointMode改為points
PointMode改為polygon, PointMode改為polygon,相鄰點互相連接
PointMode改為lines窃这。 PointMode為lines時瞳别,兩個點相互連接,也就是說第一個和第二個點連接钦听,第三個跟第四個連接洒试,如果最后只有一個點就舍棄不連接了,在我們的例子中有7個點朴上,所以圖中只有三條連線垒棋。
繪制圓drawCircle
參數(shù)分別為:圓心的坐標、半徑和paint即可痪宰。圓形是否填充或描邊(或兩者)由Paint.style控制叼架。
void drawCircle(Offset c, double radius, Paint paint)
class MyPainter extends CustomPainter {
///[定義畫筆]
Paint _paint = Paint()
..color = Colors.blueAccent //畫筆顏色
..strokeCap = StrokeCap.round//畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒
..style = PaintingStyle.stroke //繪畫風格,默認為不填充
..strokeWidth = 5.0; //畫筆的寬度
@override
void paint(Canvas canvas, Size size) {
//繪制圓 參數(shù)(圓心衣撬,半徑乖订,畫筆)
canvas.drawCircle(Offset(140,80), 80,_paint..color = Colors.green);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return null;
}
}
PaintStyle.fill 填充
繪制橢圓drawOval
制一個軸對稱的橢圓形,參數(shù)為一個矩形和畫筆paint.
void drawOval(Rect rect, Paint paint)
class MyPainter extends CustomPainter {
///[定義畫筆]
Paint _paint = Paint()
..color = Colors.blueAccent //畫筆顏色
..strokeCap = StrokeCap.round//畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒
..style = PaintingStyle.fill //繪畫風格具练,默認為填充
..strokeWidth = 5.0; //畫筆的寬度
@override
void paint(Canvas canvas, Size size) {
//使用左上和右下角坐標來確定矩形的大小和位置,橢圓是在這個矩形之中內(nèi)切的
Rect rect = Rect.fromPoints(Offset(100.0, 40.0), Offset(220.0, 100.0));
canvas.drawOval(rect, _paint..color=Colors.green);
}
}
Rect也有多種構(gòu)建方式: fromLTWH(double left, double top, double width, double height) 使用矩形左邊的X坐標乍构、矩形頂部的Y坐標矩形的寬高來確定矩形的大小和位置
@override
void paint(Canvas canvas, Size size) {
//使用矩形左邊的X坐標、矩形頂部的Y坐標矩形的寬高來確定矩形的大小和位置
Rect rect = Rect.fromLTWH(100, 20, 100, 60);
canvas.drawOval(rect, _paint..color=Colors.green);
}
fromLTRB(double left, double top, double right, double bottom) 使用矩形左邊的X坐標扛点、矩形頂部的Y坐標哥遮、矩形右邊的X坐標岂丘、矩形底部的Y坐標來確定矩形的大小和位置
@override
void paint(Canvas canvas, Size size) {
//使用矩形左邊的X坐標、矩形頂部的Y坐標眠饮、矩形右邊的X坐標奥帘、矩形底部的Y坐標來確定矩形的大小和位置
Rect rect = Rect.fromLTRB(30, 30, 160, 140);
canvas.drawOval(rect, _paint..color=Colors.green);
}
fromCircle({ Offset center, double radius }) 使用圓的圓心點坐標和半徑和確定外切矩形的大小和位置
@override
void paint(Canvas canvas, Size size) {
//使用圓的圓心點坐標和半徑和確定外切矩形的大小和位置
Rect rect = Rect.fromCircle(center: Offset(100, 40),radius: 60);
canvas.drawOval(rect, _paint..color=Colors.green);
}
繪制圓弧drawArc
首先還是需要Rect來確認圓弧的位置,還需要開始的弧度仪召、結(jié)束的弧度寨蹋、是否使用中心點繪制(圓弧是否向中心閉合)、以及paint.
void drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint)
class MyPainter extends CustomPainter {
///[定義畫筆]
Paint _paint = Paint()
..color = Colors.blueAccent //畫筆顏色
..strokeCap = StrokeCap.round//畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒
..style = PaintingStyle.fill //繪畫風格扔茅,默認為填充
..strokeWidth = 5.0; //畫筆的寬度
@override
void paint(Canvas canvas, Size size) {
// Rect來確認圓弧的位置已旧,還需要開始的弧度、結(jié)束的弧度咖摹、是否使用中心點繪制评姨、以及paint弧度
Rect rect = Rect.fromCircle(center: Offset(100, 40),radius:80);
canvas.drawArc(rect,0.0,0.8,false,_paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return null;
}
}
圓弧向中心點閉合 將useCenter改成true,圓弧向中心點閉合了
@override
void paint(Canvas canvas, Size size) {
// Rect來確認圓弧的位置萤晴,還需要開始的弧度、結(jié)束的弧度胁后、是否使用中心點繪制店读、以及paint弧度
const PI = 3.1415926;
Rect rect2 = Rect.fromCircle(center: Offset(100.0, 50.0), radius: 80.0);
canvas.drawArc(rect2, 0.0, PI / 2, true, _paint);
}
繪制圓角矩形drawDRRect
class MyPainter extends CustomPainter {
///[定義畫筆]
Paint _paint = Paint()
..color = Colors.blueAccent //畫筆顏色
..strokeCap = StrokeCap.round//畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒
..style = PaintingStyle.stroke //繪畫風格,默認為填充
..strokeWidth = 5.0; //畫筆的寬度
@override
void paint(Canvas canvas, Size size) {
//用Rect構(gòu)建一個邊長50,中心點坐標為100,100的矩形
Rect rect = Rect.fromCircle(center: Offset(140.0, 50.0), radius: 50.0);
//根據(jù)上面的矩形,構(gòu)建一個圓角矩形
RRect rrect = RRect.fromRectAndRadius(rect, Radius.circular(20.0));
canvas.drawRRect(rrect, _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return null;
}
}
繪制路徑drawPath
繪制路徑攀芯,首先需要一個要繪制的路徑path屯断,然后就是這個paint了。
方法名 作用
moveTo 將路徑起始點移動到指定的位置
relativeMoveTo 相對于當前位置移動到
lineTo 從當前位置連接指定點
relativeLineTo 相對當前位置連接到
arcTo 曲線
conicTo 貝塞爾曲線
add** 添加其他圖形侣诺,如addArc殖演,在路徑是添加圓弧
contains 路徑上是否包括某點
transfor 給路徑做matrix4變換
combine 結(jié)合兩個路徑
close 關(guān)閉路徑,連接路徑的起始點
reset 重置路徑年鸳,恢復到默認狀態(tài)
class MyPainter extends CustomPainter {
///[定義畫筆]
Paint _paint = Paint()
..color = Colors.blueAccent //畫筆顏色
..strokeCap = StrokeCap.round//畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒
..style = PaintingStyle.stroke //繪畫風格趴久,默認為填充
..strokeWidth = 5.0; //畫筆的寬度
@override
void paint(Canvas canvas, Size size) {
//新建了一個path,然后將路徑起始點移動到坐標(100,100)的位置
Path path = new Path()..moveTo(100.0, 100.0);
path.lineTo(200.0, 200.0);
canvas.drawPath(path, _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return null;
}
}
繪制多個路徑
@override
void paint(Canvas canvas, Size size) {
Path path = new Path()..moveTo(100.0, 100.0);
path.lineTo(200.0, 200.0);
path.lineTo(100.0, 300.0);
path.lineTo(150.0, 350.0);
path.lineTo(150.0, 500.0);
canvas.drawPath(path, _paint);
}