先看效果:


其实整个动画过程分为两部分,整体的旋转和两条线的增长和缩短。分解如下:


关键部分代码在onDraw方法,实现如下(完整代码):
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制阴影
canvas.drawArc(shadowRect, topDegree, arc, false, mShadowPaint);
canvas.drawArc(shadowRect, bottomDegree, arc, false, mShadowPaint);
//绘制彩色线条
canvas.drawArc(loadingRect, topDegree, arc, false, mPaint);
canvas.drawArc(loadingRect, bottomDegree, arc, false, mPaint);
//线条的起始位置,通过不断改变起始位置实现旋转
topDegree += speedOfDegree;
bottomDegree += speedOfDegree;
//转一周后置零
if (topDegree > MAX_DEGREE) {
topDegree = topDegree - MAX_DEGREE;
}
if (bottomDegree > MAX_DEGREE) {
bottomDegree = bottomDegree - MAX_DEGREE;
}
//线条的增长和颜色变化逻辑circleFlag初始值为true,colorFlag初值为false
if (circleFlag) {
if (colorFlag) {
//一个周期后开始换颜色,colorFlag在线条减小时为true
colorFlag = !colorFlag;
flag++;
mPaint.setColor(COLORS[flag % COLORS.length]);
}
//线条未增加到最大值时增加
if (arc < MAX) {
arc += speedOfArc;
invalidate();
}
} else {
if (!colorFlag) {
colorFlag = !colorFlag;
}
//线条未减小到最小值时减小
if (arc > MIN) {
arc -= 2 * speedOfArc;
invalidate();
}
}
//若增加或缩小超过合法返回时,反置线条的增长或缩小
if (arc >= MAX || arc <= MIN) {
circleFlag = !circleFlag;
invalidate();
}
}
实际上通过分解动画来思考,这个加载动画还是很简单的,当然还有其他很多实现方法,比如旋转时可以利用画布旋转实现。
这只是我一个项目中的一个简单控件,没有将一些值做成控件属性的形式,而是直接写固定,感兴趣的朋友可以将代码直接复制到工程中使用。