几乎所有的UI系统都会提供一个自绘UI的接口,这个接口通常会提供一块2D画布Canvas,Canvas内部封装了一些基本绘制的API,开发者可以通过Canvas绘制各种自定义图形。在Flutter中,提供了一个CustomPaint 组件,它可以结合画笔CustomPainter来实现自定义图形绘制。
1 CustomPaint
CustomPaint({
Key key,
this.painter,
this.foregroundPainter,
this.size = Size.zero,
this.isComplex = false,
this.willChange = false,
Widget child, //子节点,可以为空
})
painter: 背景画笔,会显示在子节点后面;foregroundPainter: 前景画笔,会显示在子节点前面size:当child为null时,代表默认绘制区域大小,如果有child则忽略此参数,画布尺寸则为child尺寸。如果有child但是想指定画布为特定大小,可以使用SizeBox包裹CustomPaint实现。isComplex:是否复杂的绘制,如果是,Flutter会应用一些缓存策略来减少重复渲染的开销。willChange:和isComplex配合使用,当启用缓存时,该属性代表在下一帧中绘制是否会改变。
可以看到,绘制时需要提供前景或背景画笔,两者也可以同时提供。的画笔需要继承CustomPainter类,我们在画笔类中实现真正的绘制逻辑。
CustomPainter与Canvas
CustomPainter中提定义了一个虚函数paint:
void paint(Canvas canvas, Size size);
paint有两个参数:
-
Canvas:一个画布,包括各种绘制方法,我们列出一下常用的方法:API名称 功能 drawLine 画线 drawPoint 画点 drawPath 画路径 drawImage 画图像 drawRect 画矩形 drawCircle 画圆 drawOval 画椭圆 drawArc 画圆弧 -
Size:当前绘制区域大小。
画笔Paint
现在画布有了,我们最后还缺一个画笔,Flutter提供了Paint类来实现画笔。在Paint中,我们可以配置画笔的各种属性如粗细、颜色、样式等。如:
var paint = Paint() //创建一个画笔并配置其属性
..isAntiAlias = true //是否抗锯齿
..style = PaintingStyle.fill //画笔样式:填充
..color=Color(0x77cdb175);//画笔颜色
大总结:
自绘控件非常强大,理论上可以实现任何2D图形外观,实际上Flutter提供的所有组件最终都是通过调用Canvas绘制出来的,只不过绘制的逻辑被封装起来了,读者有兴趣可以查看具有外观样式的组件源码,找到其对应的RenderObject对象,如Text对应的RenderParagraph对象最终会通过Canvas实现文本绘制逻辑