24.Flutter:使用CustomPaint構建酷炫的Widget

CoorChice發表於2019-03-22

目錄傳送門:《Flutter快速上手指南》先導篇

到目前為止,Flutter 已經提供了 30 多種不同的 Widget 用於組合構建檢視。

但對於一些複雜的檢視,用 SDK 提供的這些 Widget 仍然無法組合出來 ? 。

我們必須自己繪製這些檢視,就像在 Android 中使用 Canvas 和 Paint 來進行繪製那樣 ? 。

在 Flutter 中,當然也有可以讓你自由繪製的方案,他就是 CustomPaint

CustomPaint

CustomPaint 也是一個 Widget。

你可把它嵌到檢視樹的任意一個節點位置。

先看看它的常用屬性:

屬性型別說明
painterCustomPainter背景畫筆,繪製內容會顯示在child子節點後面
foregroundPainterCustomPainter前景畫筆,繪製內容會顯示在child子節點前面
sizeSize設定繪製區域的大小。如果有child,則忽略該引數,且繪製區域為child的尺寸
isComplexbool是否複雜的繪製,如果是,Flutter會應用一些快取策略來減少重複渲染的開銷。預設false
willChangebool和isComplex配合使用,當啟用快取時,該屬性代表在下一幀中繪製是否會改變。預設false
childWidget沒錯,CustomPaint是可以包含一個子節點的

從 CustomPaint 的屬性可以看出,實際繪製是通過 CustomPainter 來完成的。

以 child 為基準,CustomPainter 分為兩個部分,一個是繪製在 child 上面的 pinter,一個是繪製在 child 下面的 foregroundPainter

? 看個例子:

CustomPaint(
    isComplex: true,
    willChange: true,
    size: Size(deviceSize.width, deviceSize.height),
    painter: GamePainter(background, maliao, position),
    foregroundPainter: ForegroundGamePainter(),
  )
複製程式碼

馬良神筆 CustomPainter

CustomPainter 是一個抽象類,你需要繼承它實現自己的邏輯。

class MyPainter extends CustomPainter {

  @override
  paint(Canvas canvas, Size size)  {
    ...
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
複製程式碼

繼承 CustomPainter 最重要的是實現 paint(Canvas canvas, Size size)shouldRepaint(CustomPainter oldDelegate) 這兩個函式。

  • paint() 中是繪製邏輯,可以在這獲得畫布 Canvas 和 畫布的大小 Size

  • shouldRepaint() 返回 true 才會進行重繪,否則就只會繪製一次。你可以通過一些條件判斷來決定是否每次繪製,這樣能夠節約系統資源。

實現 CustomPainter 最重要的就是在 paint() 中寫繪製邏輯。

? 一個例子:

class MyPainter extends CustomPainter {
  @override
  void paint(ui.Canvas canvas, ui.Size size) {
    Paint paint = Paint()
      ..isAntiAlias = true
      ..color = Colors.blueAccent
      ..strokeWidth = 10
      ..style = PaintingStyle.fill;

    canvas.drawLine(Offset(10, 10), Offset(250, 250), paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
複製程式碼

? 看看效果:

在繪製過程中,有兩個重要的角色:PaintCanvas

Paint

Paint 是畫筆,在 Canvas 上作畫就是依靠它去 "執行" 的。

看看 Paint 有那些常用屬性:

屬性型別說明
isAntiAliasbool是否開啟抗鋸齒,開啟抗鋸齒能夠是邊緣平滑,當然也更消耗系統資源
colorColor顏色
colorFilterColorFilter會對顏色進行變換
filterQualityFilterQuality設定繪製的影像質量
invertColorsbool是否使用反向顏色。繪製圖片時也能夠反轉圖片的顏色
maskFilterMaskFilter設定遮罩效果。比如高斯模糊
shaderShader漸變顏色。會覆蓋color
strokeCapStrokeCap設定繪製形狀的邊緣風格。如圓角、方形等
strokeJoinStrokeJoin設定兩個繪製形狀銜接處的風格。如圓角、方形等
strokeWidthdouble畫筆的寬度
stylePaintingStyle填充方式。PaintingStyle.fill-充滿;PaintingStyle.stroke-空心
blendModeBlendMode畫素混合模式。當畫一個shape或者合成圖層的時候會生效。

以上就是 Paint 常用的屬性,你可以都試試看看效果。

這是一段 Paint 的配置程式碼:

Paint paint = Paint()
  ..isAntiAlias = true
  ..color = Colors.redAccent
  ..strokeWidth = 10
  ..style = PaintingStyle.fill
  ..filterQuality = FilterQuality.high
  ..strokeCap = StrokeCap.round
  ..strokeJoin = StrokeJoin.round
  ..maskFilter = MaskFilter.blur(BlurStyle.normal, 50)
  ..invertColors = false
  ..blendMode = BlendMode.color
  ..shader = ui.Gradient.linear(
      Offset(0, 0), Offset(100, 100), [Colors.red, Colors.blueAccent])
複製程式碼

Canvas

Canvas 作為畫布,它和在 Android 使用的 Canvas 在很多介面上很像。

它包含了很多基礎的繪製操作,通過組合這些基礎的繪製操作,可以繪製出幾乎任何的檢視。

Canvas 的操作主要有兩類:

  • 針對 Canvas 的變換操作,如平移、旋轉、縮放、圖層等操作。

  • 繪製基礎圖形的操作,如線段、路徑、圖片、幾何圖形等。

Canvas 的這些操作後續再詳細講解 ?。

目錄傳送門:《Flutter快速上手指南》先導篇

如何找到我?

傳送門:CoorChice 的主頁

傳送門:CoorChice 的 Github


相關文章