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

发布了22 篇原创文章 · 获赞 17 · 访问量 6932

猜你喜欢

转载自blog.csdn.net/u013491829/article/details/104764021
今日推荐