Flutter圈子随笔-生活工作点滴Flutter

十、Flutter加载动画

2019-08-04  本文已影响29人  星星编程

目录
一、效果展示
二、RoundPainter
三、RoundProgress
四、旋转起来
五、停止旋转

一、效果展示

Flutter加载动画.jpg

二、RoundPainter

同上篇文章《九、Flutter水波动画》画水波原理是一样的,都是通过画笔呈现不规则图形。this.offsetList是存储加载的动画里面的实心圆的坐标,通过drawCircle方法把坐标画到画布上。

 @override
  void paint(Canvas canvas, Size size) {
    for (int i = 0; i < this.offsetList.length; i++) {
      var paint = new Paint()
      ..color = this.color
      ..style = PaintingStyle.fill;
      canvas.drawCircle(this.offsetList[i], this.radiusList[i], paint);
    }
  }

三、RoundProgress

RoundProgress继承StatefulWidget通过 Timer刷新页面,来达到动画的效果。this.w * i / this.numOfMoveView是计算每个实心圆的宽度的,i越小实心圆的宽度越小,实心圆就越小。(pi * 2.0 / this.numOfMoveView) * i计算出弧度,通过弧度计算出每个实心圆的坐标,保存在this.offsetList里。每个实心圆初始化的弧度都保存在了 this.radianList里,循环第二次,第三次......累计弧度,每个实心圆的坐标逐一按弧度偏移,从而所有的实心圆绕着一个点旋转。

  this.timer = Timer.periodic(new Duration(milliseconds: 80), (timer) {
      setState(() {
        double r = this.width;
        if (r > this.height) {
          r = this.height;
        }
        r = r / 2.0;
        r = r * this.moveSize;
        double w = r * sin(2 * pi / this.numOfMoveView) / 2.0;
        r -= (w / 2.0);
        w = w * this.moveViewSize;
        this.r = r;
        this.w = w;
        List<Offset> oList = [];
        List<double> rList = [];
        List<double> radianList = [];

        for (int i = 1; i < this.numOfMoveView + 1; i++) {
          w = this.w * i / this.numOfMoveView;
          double radian = (pi * 2.0 / this.numOfMoveView) * I;
          Offset offset = Offset(this.width / 2.0 + this.r * cos(radian),
              this.r * sin(radian) + this.height / 2.0);
          if (this.radianList.length > 0) {
            radian = this.radianList[i - 1] +  pi * 2.0 / (2.0 *this.numOfMoveView);
            offset = Offset(this.width / 2.0 + this.r * cos(radian),
                this.height / 2.0 + this.r * sin(radian));
          }
          oList.add(offset);
          rList.add(w / 2.0);
          radianList.add(radian);
        }
        this.offsetList = oList;
        this.radiusList = rList;
        this.radianList = radianList;
      });
    });

四、旋转起来

RoundProgress最重的一个参数loading,当loading = true加载动画会在stack里面呈现出来,当loading = false加载动画不会出现在stack里面。

 this.loading = true;
  
 RoundProgress(
        key: this.key,
        loading: this.loading,
        width: 160,
        height: 160,
        child: Center(
            child: Center(
            child: Text("正在加载数据..."),
        )),
      ),

五、停止旋转

由于RoundProgress继承了StatefulWidget,从外部就没有办法更新RoundProgress数据了,可以通过组件间通信。这里使用的是Global Key通信,可以访问State对象的公共属性和方法,从而让加载动画停止旋转,刷新组件。另外还有一种通信方法是ValueNotifier通信,ValueNotifier是一个包含单个值的变更通知器,当它的值改变的时候,会通知它的监听。

final key = GlobalKey<RoundProgressState>();

 setState(() {
        this.loading = false;
        this.key.currentState.updateLoad(this.loading);
        this.updateChild();
      });

总结:这个加载动画算是初步完成了,基本使用还是可以的,封装的不够灵活,可自定义程度比较低。下一篇文章将进一步对加载动画优化,并上传到pub.dev方便大家使用。谢谢收看,点个赞吧!

关注公众号,查看更多内容.jpg
上一篇下一篇

猜你喜欢

热点阅读