flutter 用 CustomPaint 绘制自定义图案
什么是CustomPaint?
在Android中,有时候我们需要使用 Canvas 和 Paint 来进行绘制一些复杂的图形,在 Flutter 中,当然也有可以让你自由绘制的方案,他就是 CustomPaint。
CustomPaint 也是一个 Widget,你可以把它嵌到视图树的任意一个节点位置。
先看看它的常用属性:
属性 | 类型 | 说明 |
---|---|---|
painter | CustomPainter | 背景画笔,绘制内容会显示在child子节点后面 |
foregroundPainter | CustomPainter | 前景画笔,绘制内容会显示在child子节点前面 |
size | Size | 设置绘制区域的大小。如果有child,则忽略该参数,且绘制区域为child的尺寸 |
isComplex | bool | 是否复杂的绘制,如果是,Flutter会应用一些缓存策略来减少重复渲染的开销。默认false |
willChange | bool | 和isComplex配合使用,当启用缓存时,该属性代表在下一帧中绘制是否会改变。默认false |
child | Widget | 没错,CustomPaint是可以包含一个子节点的 |
CustomPaint
是一个继承自SingleChildRenderObjectWidget
的控件,不能用setState的方式来刷新它。
painter
就是我们的主绘制工具,它是一个CustomPainter
;foregroundPainter
是用来绘制前景的工具;
size
为画布大小,这个size会传递给Painter
;
isComplex
和willChange
是告诉Flutter你的CustomPaint
是否复杂到需要使用cache相关的功能;
child
属性我们一般不填,即使你是想要在你的CustomPaint
上添加一些其他的布局,也不建议放在child属中性,因为你会发现你并不会得到你想要的结果。
CustomPainter 是一个抽象类,你需要继承它实现自己的逻辑。
class MyPainter extends CustomPainter {
@override
paint(Canvas canvas, Size size) {
// do
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
继承 CustomPainter 最重要的是实现 paint(Canvas canvas, Size size)
和 shouldRepaint(CustomPainter oldDelegate)
这两个函数。
paint()
中是绘制逻辑,可以在这获得画布 Canvas 和 画布的大小 Size。shouldRepaint()
返回 true 才会进行重绘,否则就只会绘制一次。你可以通过一些条件判断来决定是否每次绘制,这样能够节约系统资源。
例如:
@override
void paint(Canvas canvas, Size size) {
final outerThickess = max(trackWidth, max(progressWidth, thumbSize));
Size constrainedSize = new Size(
size.width - outerThickess,
size.height - outerThickess
);
// paint track.
final center = new Offset(size.width / 2, size.height /2);
final radius = min(constrainedSize.width, constrainedSize.height) / 2;
canvas.drawCircle(center, radius, trackPaint);
// paint progress.
final progressAngle = 2 * pi * progressPercent;
canvas.drawArc(new Rect.fromCircle(
center: center,
radius: radius
), -pi / 2, progressAngle, false, progressPaint);
// paint thumb.
final thumbAngle = 2 * pi * thumbPosition - (pi / 2);
final thumbX = cos(thumbAngle) * radius;
final thumbY = sin(thumbAngle) * radius;
final thumbCenter = new Offset(thumbX, thumbY) + center;
final thumbRadius = thumbSize / 2;
canvas.drawCircle(thumbCenter, thumbRadius, thumbPaint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
这里简单的列一下,一些常用的canvas绘制API:
// 绘制弧线
drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint)
// 绘制图片
drawImage(Image image, Offset p, Paint paint)
// 绘制圆
drawCircle(Offset c, double radius, Paint paint)
// 绘制线条
drawLine(Offset p1, Offset p2, Paint paint)
// 绘制椭圆
drawOval(Rect rect, Paint paint)
// 绘制文字
drawParagraph(Paragraph paragraph, Offset offset)
// 绘制路径
drawPath(Path path, Paint paint)
// 绘制点
drawPoints(PointMode pointMode, List<Offset> points, Paint paint)
// 绘制Rect
drawRect(Rect rect, Paint paint)
// 绘制阴影
drawShadow(Path path, Color color, double elevation, bool transparentOccluder)
1、绘制直线
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..isAntiAlias = true
..color = Colors.pink
..strokeWidth = 10
..style = PaintingStyle.fill;
Paint paint1 = Paint()
..isAntiAlias = true
..color = Colors.blue
..strokeWidth = 10
..style = PaintingStyle.fill;
Paint paint2 = Paint()
..isAntiAlias = true
..color = Colors.green
..strokeWidth = 10
..style = PaintingStyle.fill;
/// Offset(),横纵坐标偏移
canvas.drawLine(Offset(85, 100), Offset(285, 100), paint);
canvas.drawLine(Offset(85, 100), Offset(200, 300), paint1);
canvas.drawLine(Offset(285, 100), Offset(200, 300), paint2);
}
2、绘制弧线
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..isAntiAlias = true
..color = Colors.green
..strokeCap = StrokeCap.round
..strokeWidth = 10
..style = PaintingStyle.stroke;
Paint paint1 = Paint()
..isAntiAlias = true
..color = Colors.blue
..strokeCap = StrokeCap.round
..strokeWidth = 10
..style = PaintingStyle.stroke;
/// Offset(),横纵坐标偏移
/// void drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint)
/// Rect来确认圆弧的位置, 开始的弧度、结束的弧度、是否使用中心点绘制(圆弧是否向中心闭合)、以及paint.
final center = new Offset(170, 200);
canvas.drawArc(new Rect.fromCircle(
center: center,
radius: size.width / 2
), -pi / 2, 2 * pi * 0.5, false, paint);
canvas.drawArc(new Rect.fromCircle(
center: Offset(170, 300),
radius: size.width / 2
), pi / 2, 2 * pi * 0.5, false, paint1);
}
3、绘制圆
Paint paint = Paint()
..isAntiAlias = true
..color = Colors.green
..strokeCap = StrokeCap.round
..strokeWidth = 10
..style = PaintingStyle.fill;
Paint paint1 = Paint()
..isAntiAlias = true
..color = Colors.blue
..strokeCap = StrokeCap.round
..strokeWidth = 10
..style = PaintingStyle.stroke;
canvas.drawCircle(Offset(150.0, 200.0), 50.0, paint1);
canvas.drawCircle(Offset(150.0, 350.0), 50.0, paint);
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: