天天看點

Flutter 33: 圖解自定義 View 之 Paint

      Flutter 提供了與 Android 相似的 Paint 和 Canvas 來實作自定義 View,使應用更友善完善。小菜嘗試學習和使用自定義 View。

      自定義 View 包括 Paint 畫筆與 Canvas 畫布,兩部分缺一不可;兩者通過 CustomPainter 銜接使用。需要實作 paint() 繪制方法與 shouldRepaint() 在重新整理布局的時是否需要重繪。

class PaintCustom extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    // TODO: implement paint
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}           

Paint 畫筆

      Paint 畫筆有很多屬性,小菜介紹如下常用屬性;小菜以一條線和一個圓來測試。一目了然的屬性小菜就暫且略過,主要嘗試其他屬性。

color -> 畫筆顔色
strokeWidth -> 畫筆粗細
isAntiAlias -> 是否抗鋸齒
filterQuality -> 顔色渲染模式品質:高 / 中 / 低
shader -> 着色器,一般用來繪制漸變效果或 ImageShader
strokeCap -> 筆觸線帽類型:round / butt / square

      筆觸類型包括三種,預設為 butt 即從初始點到終止點;square 在初試點與終止點繪制一個方塊;round 即在初試點與終止點繪制一個圓角;

canvas.drawLine(
    Offset(30.0, 30.0), Offset(Screen.width - 30.0, 30.0), Paint());
canvas.drawLine(
    Offset(30.0, 60.0), Offset(Screen.width - 30.0, 60.0), Paint()..strokeWidth = 8.0..isAntiAlias = true);
canvas.drawLine(
    Offset(30.0, 120.0), Offset(Screen.width - 30.0, 120.0), Paint() ..strokeWidth = 8.0 ..isAntiAlias = true..strokeCap = StrokeCap.round);
canvas.drawLine(
    Offset(30.0, 90.0), Offset(Screen.width - 30.0, 90.0), Paint()..strokeWidth = 8.0..isAntiAlias = true..strokeCap = StrokeCap.square);           
strokeJoin -> 線結合處:銳角 / 圓弧 / 直線

      線上的交彙點處,可以設定交疊時樣式,包括:銳角,圓弧和直角樣式,

官方效果

更直接。

style -> 畫筆樣式:填充 / 描邊

      style 包括兩種樣式,預設 PaintingStyle.fill 為填充,PaintingStyle.stroke 為描邊;用圓來繪制效果更明顯;

canvas.drawCircle(Offset(100.0, 200.0), 50.0, Paint()..strokeWidth = 8.0);
canvas.drawCircle(Offset(260.0, 200.0), 50.0, Paint()..strokeWidth = 8.0..style = PaintingStyle.stroke);           
maskFilter -> 模糊遮照效果

      模糊效果包括:nomal 内外模糊;solid 内部填充外邊模糊,類似于熒光燈效果;outer 内部透明外邊模糊;inner 内部模糊,外邊正常;小菜建議大家多嘗試效果;

canvas.drawLine(Offset(30.0, 280.0), Offset(Screen.width - 30.0, 280.0),
    Paint()..strokeWidth = 8.0..strokeCap = StrokeCap.round..maskFilter = MaskFilter.blur(BlurStyle.normal, 3.0));
canvas.drawLine(Offset(30.0, 310.0), Offset(Screen.width - 30.0, 310.0),
    Paint()..strokeWidth = 8.0..strokeCap = StrokeCap.round..maskFilter = MaskFilter.blur(BlurStyle.outer, 3.0));
canvas.drawLine(Offset(30.0, 340.0), Offset(Screen.width - 30.0, 340.0),
    Paint()..strokeWidth = 8.0..strokeCap = StrokeCap.round..maskFilter = MaskFilter.blur(BlurStyle.solid, 3.0));
canvas.drawLine(Offset(30.0, 370.0), Offset(Screen.width - 30.0, 370.0),
    Paint()..strokeWidth = 8.0..strokeCap = StrokeCap.round..maskFilter = MaskFilter.blur(BlurStyle.inner, 3.0));           
blendMode -> 顔色混合模式,類型很多
colorFilter -> 顔色渲染模式,一般是矩陣效果來改變

      顔色混合與顔色渲染是兩個很神奇的屬性,可以通過衆多模式調整顔色疊加效果,并與背景色銜接,小菜還無法準确的說明其中疊加的原理;

canvas.drawLine(Offset(30.0, 400.0), Offset(Screen.width - 30.0, 400.0),
    Paint()..strokeWidth = 8.0..blendMode = BlendMode.exclusion..colorFilter = ColorFilter.mode(Colors.white, BlendMode.exclusion));
canvas.drawLine(Offset(30.0, 430.0), Offset(Screen.width - 30.0, 430.0),
    Paint()..strokeWidth = 8.0..blendMode = BlendMode.exclusion..colorFilter = ColorFilter.mode(Colors.yellow, BlendMode.exclusion));
canvas.drawLine(Offset(30.0, 460.0), Offset(Screen.width - 30.0, 460.0),
    Paint()..strokeWidth = 8.0..blendMode = BlendMode.exclusion..colorFilter = ColorFilter.mode(Colors.red, BlendMode.exclusion));
canvas.drawLine(Offset(30.0, 490.0), Offset(Screen.width - 30.0, 490.0),
    Paint()..strokeWidth = 8.0..blendMode = BlendMode.exclusion..colorFilter = ColorFilter.mode(Colors.green, BlendMode.exclusion));           

      小菜對自定義 View 的了解還并不深入,有很多需要繼續學習研究的東西,如有問題,請多多指教!

繼續閱讀