Flutter:CustomPaint与RenderObject自绘摘要

一、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}");
    }
  }
}

猜你喜欢

转载自blog.csdn.net/a526001650a/article/details/127965411