Flutter 自繪組件 (CustomPaint與Canvas)繪製虛線、區域、直線(一)

   盛年不重來,一日難再晨。及時宜自勉,歲月不待人。——陶淵明

最近着手用Flutter開發一個項目,以前因爲有原生開發的經驗,所以上手比較快。

應用開發的過程中不僅僅是編碼,還需要和UI小姐姐的配合,才能完成界面。如果要求我們手動去繪製一些圓形啊、線條啊、多邊形呀;這時就比較考驗你的耐心和基本功了。

看看UI給開發的設計圖,因爲沒有提供虛線切圖,這時需要我們手動去實現一下了,不辛苦,馬上就好。

思路     

➊  多個Container 相鄰拼湊,設置間距,同時和Colum\Row搭配,實現豎線或水平線

➋  可以繪製一條水平的虛線,然後做一個旋轉90度,這樣不就是一條豎直的虛線了嗎

➌  第三種方案就是我們今天要說的CustomPaint+畫布(Canvas) 進行實現 

有人也許會疑惑,方案1和方案二不都是採用的繪製嗎,那可不一定。有的時候解決問題,我們不遵循常規也可以解決問題,滿足一時之需了。

1、解決問題奇葩方式一:

爲什麼奇葩呢?我們採用多個Container進行豎直或者水平排列完成了效果,至於性能上我們後面慢慢驗證了。

  _lineContainer() {
    return Container(
      margin: EdgeInsets.only(top: 2.0),
      color: Colors.blue,
      height: 8.0,
      width: 2.0,
    );
  }
 @override
  Widget build(BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height,
      color: Colors.white,
      padding: EdgeInsets.only(top: 100.0),
      child: Column(
        children: <Widget>[
          _lineContainer(),
          _lineContainer(),
          _lineContainer(),
          _lineContainer(),
          _lineContainer(),
          _lineContainer(),
          _lineContainer(),
          _lineContainer(),
          _lineContainer(),
          _lineContainer(),
          _lineContainer(),
          _lineContainer(),
        ],
      ),
    );
}

效果圖:

不同寬度的虛線只需要修改屬性width,達到效果。

水平虛線實現:

效果圖:

2、解決問題奇葩方式二:

多個Containter相鄰而且相同間距拼湊成水平線,然後進行一個旋轉:

  _lineContainer() {
    return Container(
      alignment: Alignment.topLeft,
      margin: EdgeInsets.only(left: 2.0),
      color: Colors.green,
      height: 2.0,
      width: 8.0,
    );
  }
 @override
  Widget build(BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height,
      color: Colors.white,
      alignment: Alignment.topLeft,
      padding: EdgeInsets.only(top: 300.0),
      child: DecoratedBox(
        decoration: BoxDecoration(color: Colors.transparent),
        child: Transform.rotate(
          //旋轉90度
          angle: math.pi / 2,
          child: Row(
            children: <Widget>[
              _lineContainer(),
              _lineContainer(),
              _lineContainer(),
              _lineContainer(),
              _lineContainer(),
              _lineContainer(),
              _lineContainer(),
              _lineContainer(),
              _lineContainer(),
              _lineContainer(),
              _lineContainer(),
              _lineContainer(),
            ],
          ),
        ),
      ),
    );
  }

效果如下:

                                 

3、今天主要提及的CustomPaint+畫布(Canvas)

涉及的幾個點:畫筆(Paint)、樣式(PaintingStyle)、color(顏色)、線條寬度(strokeWidth);

offset(第一參數,第二參數):表示第一參數和第二參數之間的偏移量。

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {

    var paint = Paint()
      ..isAntiAlias = true
      ..style = PaintingStyle.fill //填充
      ..color = Color(0x77cdb175); //背景爲紙黃色
    canvas.drawRect(Offset.zero & size, paint);

    paint
      ..style = PaintingStyle.stroke //線
      ..color = Colors.red
      ..strokeWidth = 1.0;

    for (int i = 0; i <= 35; ++i) {
      double dx = 6.0 * i;
      canvas.drawLine(Offset(dx, 20), Offset(dx, 22), paint);
    }

  }

  //在實際場景中正確利用此回調可以避免重繪開銷,本示例我們簡單的返回true
  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

引用自定義繪畫:

@override
  Widget build(BuildContext context) {
    return Container(color: Colors.white,child :Center(
      child: CustomPaint(
        size: Size(300, 300), //指定畫布大小
        painter: MyPainter(),
      ),
    ));
  }

效果漸漸離我們很近了:

   

往後多餘的時間,我會對不同畫虛線的方式優缺點做對比。

總結:

不管我們用什麼方式繪製虛線,都可以達到同樣的效果;雖然有的方式很繁瑣,但是在解決問題的時候可以認爲它不是最佳選擇。努力去嘗試,儘量以Flutter官網作爲參考,這樣纔不會違背開發的原則。

參考:自繪組件 (CustomPaint與Canvas)https://book.flutterchina.club/chapter10/custom_paint.html

container:https://book.flutterchina.club/chapter5/container.html?h=Container

變換(transform):https://book.flutterchina.club/chapter5/transform.html?h=%E6%97%8B%E8%BD%AC

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章