一、CustomPaint自绘(类似自定义View):
1.API说明:
(1)CustomPaint说明:
- CustomPaint(
- painter: ..., //背景绘制,在自定义CustomPainter中绘制背景
- foregroundPainter: ..., //前景绘制,在自定义CustomPainter中绘制前景
- size: Size(宽, 高), //child为空时指定画布宽高,child不为空时忽略此参
- isComplex: false, //是否复杂绘制,是时用缓存策略(提高性能),否时不用
- willChange: false, //true时下一帧绘制会改变,false时不改变。isComplex=true时生效
- child: ... //子布局,可以为空
- )
(2)Canvas画布:
- canvas.drawLine(开始点Offset, 结束点Offset, 画笔Paint); //画线
- canvas.drawPoint(画笔Paint); //画点
- canvas.drawPath(路径Path, 画笔Paint); //画路径
- canvas.drawImage(图片Image, 左上角Offset, 画笔Paint); //画图像
- canvas.drawRect(Rect矩形, Paint画笔); //画矩形
- canvas.drawCircle(圆心Offset, 半径数值, 画笔Paint); //画圆
- canvas.drawOval(Rect矩形, Paint画笔); //画椭圆
- canvas.drawArc(Rect矩形, 开始角度, 持续角度, true扇区或false圆环, 画笔Paint); //画圆弧
(3)Paint画笔:
- Paint paint = Paint()
- ..isAntiAlias = true //true抗锯齿,false有锯齿
- ..style = PaintingStyle.stroke //画笔样式
- ..strokeWidth = 2 //画笔粗细
- ..color = Colors.red; //画笔颜色
(4)RepaintBoundary能提高性能:
- RepaintBoundary(//使用RepaintBoundary包裹CustomPaint,使自定义绘制不受Widget树影响,减少CustomPaint重绘
- child: ...
- )
2.实现CustomPaint自绘:
(1)实现自定义CustomPainter,绘制图形:
- class MyCustomPainter extends CustomPainter {
- @override
- void paint(Canvas canvas, Size size) {
- //...在此处绘制自定义图形,例画路径
- Path path = Path()
- ..moveTo(0, 150)
- ..lineTo(100, 0)
- ..lineTo(200, 120)
- ..lineTo(300, 50);
- canvas.drawPath(path, mPaint); //画路径
- }
- @override
- bool shouldRepaint(CustomPainter oldDelegate) => false; //false不会重绘, true会重绘
- }
(2)创建CustomPaint,并传入自定义CustomPainter:
- RepaintBoundary( //使用RepaintBoundary包裹CustomPaint,使自定义绘制不受Widget树影响,减少CustomPaint重绘
- child: CustomPaint(
- painter: MyCustomPainter(), //背景绘制,在自定义CustomPainter中绘制背景
- foregroundPainter: MyCustomPainter(), //前景绘制,在自定义CustomPainter中绘制前景
- size: Size(200, 100) //指定画布宽高
- )
- );
二、RenderObject自绘:
1.实现自定义RenderObjectWidget类:
- class MyRenderObjectWidget extends LeafRenderObjectWidget{ //LeafRenderObjectWidget为RenderObjectWidget子类
- @override
- RenderObject createRenderObject(BuildContext context) {
- return MyRenderObject(); //此处创建自定义RenderObject
- }
- @override
- void updateRenderObject(context, MyRenderObject renderObject) {
- //...此处更新自定义RenderObject状态
- }
- }
2.实现自定义RenderObject类:
- class MyRenderObject extends RenderBox{ //RenderBox为RenderObject子类
- int pointer = 0;
- @override
- bool get isRepaintBoundary => true;
- //测绘方式1,size由本组件决定
- @override
- void performLayout() {
- //父Widget有固定宽高时使用父的,没有则此处指定默认值
- size = constraints.constrain(constraints.isTight ? Size.infinite : Size(100, 100));
- }
- //测绘方式2,size由parent组件决定,必须sizedByParent返回true
- // @override
- // void performResize() {
- // size = constraints.biggest;
- // }
- // @override
- // bool get sizedByParent => true;
- @override
- void paint(PaintingContext context, Offset offset) {//paint方法实现自定义绘图
- //...绘图逻辑
- }
- @override
- bool hitTestSelf(Offset position) => true; //true时响应点击事件,false忽略点击事件
- @override
- void handleEvent(PointerEvent event, covariant BoxHitTestEntry entry) { //处理点击事件
- if (event.down) {
- pointer = event.pointer;
- return;
- }
- if (event.pointer == pointer && size.contains(event.localPosition)) { //判断点击是否在本组件内
- log("触发点击了 handleEvent >> pointer: ${event.pointer} localPosition: ${event.localPosition}");
- }
- }
- }