Flutter 自定義繪製 View

StefanJi發表於2019-03-17

在 Flutter 中自定義 View 有兩種方式:

  1. 組合已有控制元件
  2. 自定義繪製

如何自定義繪製

有兩個類做這件事情:

  • CustomPaint :會在繪製階段提供一個 Canvas 畫布
  • CustomPainter : 具體的畫筆, 可配置畫筆的顏色,路徑等
CustomPaint(
  painter: Sky(),
  child: Center(
    child: Text(
      'Once upon a time...',
      style: const TextStyle(
        fontSize: 40.0,
        fontWeight: FontWeight.w900,
        color: Color(0xFFFFFFFF),
      ),
    ),
  ),
)
複製程式碼

當在繪製階段時, CustomPaint 首先會呼叫 painter 在畫布上進行繪製, 然後再繪製它的 child 控制元件, child 繪製完成之後會呼叫 foregroundPainter 進行繪製. 畫布的座標系和 CustomPaint 的座標系匹配. CustomPaint 有個 Size 屬性標識將繪製多大的區域, 繪製時這個 Size 屬性將會傳遞到 CustomPainterpaint 方法中, 具體的繪製就在paint 方法中進行, void paint(Canvas canvas, Size size); 的方法簽名中的兩個引數:

  • canvas: 用於繪製的畫布, 注意: 該畫布是應用所有控制元件都在使用的, 所以通過這個畫布其實是可以繪製充滿螢幕的內容的
  • size: 表示應該繪製的區域大小, 每次繪製都應該限制在這個區域內, 否則可能會覆蓋了其他控制元件的繪製結果

例項一

繪製一個矩形和圓角:

flutter 自定義繪製

Widget build(BuildContext context) {
  return CustomPaint(
    painter: ColorPainter(),
    size: Size(300, 200),
  );
}
複製程式碼
class ColorPainter extends CustomPainter {

  final red = Color.fromRGBO(255, 0, 0, 1);
  final blue = Color.fromRGBO(0, 0, 255, 1);
 
  @override
  void paint(Canvas canvas, Size size) {  
    final paint = Paint();
    final rect = Rect.fromLTRB(0.0, 0.0, size.width, size.height);
    // 注意這一句
    canvas.clipRect(rect);
    paint.color = blue;
    canvas.drawRect(rect, paint);
    paint.color = red;
    canvas.drawCircle(Offset.zero, size.height, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}
複製程式碼
  • 定義了繪製區域大小, 為 CustomPaint 中的 size 屬性
    final rect = Rect.fromLTRB(0.0, 0.0, size.width, size.height);
複製程式碼
  • 繪製矩形區域
    canvas.drawRect(rect, paint);
複製程式碼
  • 繪製圓形
    • 圓心偏移量為: 0, 也就是 CustomPaint 的原點
    • 半徑為區域的高度
    canvas.drawCircle(Offset.zero, size.height, paint);
複製程式碼

最需要注意的地方我覺得是 canvas.clipRect(rect); 這句. 這句表示只繪製給定的區域中的內容. 如果不寫這句, 效果就是這樣:

flutter 自定義繪製

為什麼會這樣呢 ?

其實這就是 Size 這個引數的重要性, 因為 Canvas 是被所有控制元件公有的, 如果我們繪製時不指定區域大小, 那在進行一些形狀的繪製時就會出現超出區域的問題.

例項二: 繪製一個帶波紋的 CardView

  • 支援顏色配置
  • 支援組合外部控制元件 原始碼: wave_card.dart
    flutter wave card

相關文章