目录
一、效果展示
二、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
网友评论