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

 

 

  • 76
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 29
    评论
在使用 Flutter 开发微信悬浮窗时,需要使用到 Flutter 的自组件。自组件Flutter 提供的一种自定义绘制 UI 的方式,它可以让开发者自由地控制 UI 的绘制过程,达到更高的自由度和灵活度。 在本篇文章中,我们将介绍如何使用 Flutter 的自组件来实现微信悬浮窗。首先,我们需要创建一个自组件,并在其中实现绘制逻辑。代码如下: ```dart class FloatWidget extends LeafRenderObjectWidget { @override RenderObject createRenderObject(BuildContext context) { return _FloatRenderBox(); } } class _FloatRenderBox extends RenderBox { @override void performLayout() { size = constraints.biggest; } @override void paint(PaintingContext context, Offset offset) { var canvas = context.canvas; var paint = Paint() ..color = Colors.green ..style = PaintingStyle.fill; canvas.drawCircle( Offset(size.width / 2, size.height / 2), size.width / 2, paint); } } ``` 上述代码中,`FloatWidget` 是一个自组件,它返回一个 `_FloatRenderBox` 实例。在 `_FloatRenderBox` 中,我们实现了 `performLayout` 方法和 `paint` 方法。 `performLayout` 方法用于指定组件的大小,这里我们将组件的大小设置为最大限制。`paint` 方法则用于实现具体的绘制逻辑,这里我们绘制了一个绿色的圆形。 接下来,我们可以将 `FloatWidget` 添加到我们的界面中,代码如下: ```dart class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ // ... Positioned( right: 20, bottom: 20, child: FloatWidget(), ), ], ), ); } } ``` 在上述代码中,我们使用了 `Positioned` 组件将 `FloatWidget` 定位在屏幕的右下角。现在运行程序,你就可以看到一个绿色的圆形出现在你的屏幕右下角了。 当然,这只是一个简单的例子,实现一个完整的悬浮窗还需要更多的细节处理。但是通过这个例子,你应该已经掌握了 Flutter组件的基本使用方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

️ 邪神

你自己看着办,你喜欢打赏我就赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值