十、Flutter加载动画

作者: 星星编程 | 来源:发表于2019-08-04 20:12 被阅读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

    相关文章

      网友评论

        本文标题:十、Flutter加载动画

        本文链接:https://www.haomeiwen.com/subject/zablkctx.html