Flutter CustomPaint 使用介紹

CustomPaint 介紹

CustomPaint class提供了讓用戶自定義widget的能力,它暴露了一個canvas,可以通過這個canvas來繪制widget,CustomPaint會先調(diào)用painter繪制背景,然后再繪制child,最后調(diào)用foregroundPainter來繪制前景,CustomPaint的定義如下

CustomPaint({Key key, 
      CustomPainter painter,
      CustomPainter foregroundPainter,
      Size size: Size.zero, 
      bool isComplex: false, 
      bool willChange: false, 
      Widget child })
  • painter:負責(zé)繪制背景的painter
  • foregroundPainter : 負責(zé)繪制前景的painter
  • size : 控件大小
  • isComplex : 是否復(fù)雜繪制,需要用cache來提高繪制效率
  • willChange : 和isComplex配合使用,當(dāng)啟用緩存時,該屬性代表在下一幀中繪制是否會改變
  • child : 子widget

CustomPainter 介紹

CustomPaint的繪制過程都將會交給CustomPainter來完成,CustomPainter是個抽象接口,在子類化CustomPainter的時候必須要重寫它的paintshouldRepaint接口,可以根據(jù)自己的場景來選擇性的重寫hitTestshouldRebuildSemantics方法。

  • paint : 每當(dāng)CustomPaint需要重繪的時候都會調(diào)用此接口
  • shouldRepaint : 當(dāng)CustomPaint被重新設(shè)置了一個新的painter后會回調(diào)此方法,CustomPaint會根據(jù)shouldRepaint的返回值來判斷是否需要重新繪制ui,譬如新的painter跟舊的painter繪制的內(nèi)容不一樣時,此時shouldRepaint需要返回true來通知CustomPaint重新繪制。

Canvas 介紹

canvas--畫布,真正的繪制是由canvas跟paint來完成的,畫布提供了各種繪制的接口來繪制圖形,除此以外畫布還提供了平移、縮放、旋轉(zhuǎn)等矩陣變換接口,畫布都有固定大小跟形狀,還可以使用畫布提供的裁剪接口來裁剪畫布的大小形狀等等。
常用的繪制接口有更多請查看官方文檔

//畫圓
drawCircle(Offset c, double radius, Paint paint) → void
//畫圖片
drawImage(Image image, Offset p, Paint paint) → void
//畫九宮圖
drawImageNine(Image image, Rect center, Rect dst, Paint paint) → void
//畫線
drawLine(Offset p1, Offset p2, Paint paint) → void
//畫橢圓
drawOval(Rect rect, Paint paint) → void
//畫文字
drawParagraph(Paragraph paragraph, Offset offset) → void
//畫Rect區(qū)域
drawRect(Rect rect, Paint paint) → void
//畫陰影
drawShadow(Path path, Color color, double elevation, bool transparentOccluder) → void

Paint 介紹

Paint---筆畫,是用來設(shè)置在畫布上面繪制圖形時的一些筆畫屬性,如:顏色、線寬、繪制模式、抗鋸齒等等。常用屬性有更多請查看官方文檔
color : 設(shè)置畫筆顏色
isAntiAlias : 設(shè)置畫筆是否扛鋸齒
shader : 著色器,填充形狀或者畫線時用到,如果沒設(shè)置將會使用color
strokeWidth : 設(shè)置畫筆畫線寬度
style :繪制模式,畫線或充滿

CustomPaint 使用

下面這個例子來自于官方,通過CustomPaint 畫出了一個藍天跟太陽出來

class HomeState extends State<HomeWidget> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('CustomPaintDemo'),),
      body: Container(
        alignment: Alignment.center,
        child: CustomPaint(
          painter: Sky(),
          child: Center(
            child: Text(
              'Once upon a time...',
              style: const TextStyle(
                fontSize: 40.0,
                fontWeight: FontWeight.w900,
                color: Color(0xFFFFFFFF),
              ),
            ),
          ),
        )
      ),
    );
  }
}

class Sky extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    var rect = Offset.zero & size;
    var gradient = RadialGradient(
      center: const Alignment(0.7, -0.6),
      radius: 0.2,
      colors: [const Color(0xFFFFFF00), const Color(0xFF0099FF)],
      stops: [0.4, 1.0],
    );
    canvas.drawRect(
      rect,
      Paint()..shader = gradient.createShader(rect),
    );
  }

  @override
  SemanticsBuilderCallback get semanticsBuilder {
    return (Size size) {
      // Annotate a rectangle containing the picture of the sun
      // with the label "Sun". When text to speech feature is enabled on the
      // device, a user will be able to locate the sun on this picture by
      // touch.
      var rect = Offset.zero & size;
      var width = size.shortestSide * 0.4;
      rect = const Alignment(0.8, -0.9).inscribe(Size(width, width), rect);
      return [
        CustomPainterSemantics(
          rect: rect,
          properties: SemanticsProperties(
            label: 'Sun',
            textDirection: TextDirection.ltr,
          ),
        ),
      ];
    };
  }

  // Since this Sky painter has no fields, it always paints
  // the same thing and semantics information is the same.
  // Therefore we return false here. If we had fields (set
  // from the constructor) then we would return true if any
  // of them differed from the same fields on the oldDelegate.
  @override
  bool shouldRepaint(Sky oldDelegate) => false;
  @override
  bool shouldRebuildSemantics(Sky oldDelegate) => false;
}

效果如下:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容