到目前爲止,Flutter 已經提供了 30 多種不一樣的 Widget 用於組合構建視圖。github
但對於一些複雜的視圖,用 SDK 提供的這些 Widget 仍然沒法組合出來 🙃 。canvas
咱們必須本身繪製這些視圖,就像在 Android 中使用 Canvas 和 Paint 來進行繪製那樣 🥳 。緩存
在 Flutter 中,固然也有可讓你自由繪製的方案,他就是 CustomPaint。bash
CustomPaint 也是一個 Widget。ide
你可把它嵌到視圖樹的任意一個節點位置。函數
先看看它的經常使用屬性:post
屬性 | 類型 | 說明 |
---|---|---|
painter | CustomPainter | 背景畫筆,繪製內容會顯示在child子節點後面 |
foregroundPainter | CustomPainter | 前景畫筆,繪製內容會顯示在child子節點前面 |
size | Size | 設置繪製區域的大小。若是有child,則忽略該參數,且繪製區域爲child的尺寸 |
isComplex | bool | 是否複雜的繪製,若是是,Flutter會應用一些緩存策略來減小重複渲染的開銷。默認false |
willChange | bool | 和isComplex配合使用,當啓用緩存時,該屬性表明在下一幀中繪製是否會改變。默認false |
child | Widget | 沒錯,CustomPaint是能夠包含一個子節點的 |
從 CustomPaint 的屬性能夠看出,實際繪製是經過 CustomPainter 來完成的。ui
以 child 爲基準,CustomPainter 分爲兩個部分,一個是繪製在 child 上面的 pinter
,一個是繪製在 child 下面的 foregroundPainter
。spa
🌰 看個例子:
CustomPaint(
isComplex: true,
willChange: true,
size: Size(deviceSize.width, deviceSize.height),
painter: GamePainter(background, maliao, position),
foregroundPainter: ForegroundGamePainter(),
)
複製代碼
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;
}
}
複製代碼
🖼 看看效果:
在繪製過程當中,有兩個重要的角色:Paint 和 Canvas。
Paint 是畫筆,在 Canvas 上做畫就是依靠它去 "執行" 的。
看看 Paint 有那些經常使用屬性:
屬性 | 類型 | 說明 |
---|---|---|
isAntiAlias | bool | 是否開啓抗鋸齒,開啓抗鋸齒可以是邊緣平滑,固然也更消耗系統資源 |
color | Color | 顏色 |
colorFilter | ColorFilter | 會對顏色進行變換 |
filterQuality | FilterQuality | 設置繪製的圖像質量 |
invertColors | bool | 是否使用反向顏色。繪製圖片時也可以反轉圖片的顏色 |
maskFilter | MaskFilter | 設置遮罩效果。好比高斯模糊 |
shader | Shader | 漸變顏色。會覆蓋color |
strokeCap | StrokeCap | 設置繪製形狀的邊緣風格。如圓角、方形等 |
strokeJoin | StrokeJoin | 設置兩個繪製形狀銜接處的風格。如圓角、方形等 |
strokeWidth | double | 畫筆的寬度 |
style | PaintingStyle | 填充方式。PaintingStyle.fill-充滿;PaintingStyle.stroke-空心 |
blendMode | BlendMode | 像素混合模式。當畫一個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 做爲畫布,它和在 Android 使用的 Canvas 在不少接口上很像。
它包含了不少基礎的繪製操做,經過組合這些基礎的繪製操做,能夠繪製出幾乎任何的視圖。
Canvas 的操做主要有兩類:
針對 Canvas 的變換操做,如平移、旋轉、縮放、圖層等操做。
繪製基礎圖形的操做,如線段、路徑、圖片、幾何圖形等。
Canvas 的這些操做後續再詳細講解 😉。