这是第一个

思路
1.使用SweepGradient(扫描渐变)绘制初始状态
获取到View的宽高以后,初始化圆弧的Rect,然后初始化Shader
if (width > height) {
rect.left = (width - height) / 2;
rect.right = width - rect.left;
rect.top = 0;
rect.bottom = height;
} else {
rect.left = 0;
rect.right = width;
rect.top = (height - width) / 2;
rect.bottom = height - rect.top;
}
Shader shader = new SweepGradient(width / 2, height / 2, endColor, startColor);
Matrix matrix = new Matrix();
matrix.setRotate(-90 + 20);//着色器初始位置,12点钟方法加20度,收尾留一点空隙
shader.setLocalMatrix(matrix);
- width 是View的宽度,height 是View的高度
- endColor是扫描渐变开始的颜色,对应于圆弧的尾巴,例子中颜色是#00FF0000(完全透明的纯红)
- startColor是扫描渐变结束的颜色,对应于圆弧的头,例子中颜色是#FFFF0000(完全不透明的纯红)
SweepGradient是Paint的着色器(shader)的一个实现类,可以实现雷达一样的扫描渐变,相关知识缺乏最好先去搜索
2.设置paint
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(circleThickness);
paint.setStrokeCap(Paint.Cap.ROUND);//圆头
paint.setStyle(Paint.Style.STROKE);//空心
paint.setShader(shader);//设置着色器
现在使用Canvas绘制出来的效果是这样
canvas.drawArc(rect, -90f + 30, 330f, false, paint);//圆弧初始位置是12点钟加30度,圆弧绘制330度

3.旋转
创建一个属性,和一个改变其大小的属性动画对象
private float rate = 0.0f;
public float getRate() {
return rate;
}
public void setRate(float rate) {
this.rate = rate;
refresh();
}
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "rate", 0.0f, 1.0f);
animator.setDuration(800);//800毫秒一圈
animator.setInterpolator(new LinearInterpolator());//匀速
animator.setRepeatCount(-1);//无限循环
让rate 这个属性改变乘360度(一圈),加在着色器旋转矩阵的开始角度
private void refresh() {
if (paint != null && matrix != null && shader != null) {
matrix.setRotate(-90 + 20 + 360 * rate, getWidth() / 2, getHeight() / 2);
shader.setLocalMatrix(matrix);
paint.setShader(shader);
invalidate();
}
}
让rate 这个属性改变乘360度(一圈),加在绘制圆弧的开始角度
canvas.drawArc(rect, -90f + 30 + 360 * rate, 330f, false, paint);
没错,圆弧和渐变着色器要同步。
4.动画开始和结束
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
animStart();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
animStop();
}
在关联Window时开始动画,在与Window解除关联时结束动画,一定要结束,不然会内存泄漏。
这样就完成了。

支持xml的配置
<com.riverlet.loading.CircleLoadingView
android:layout_width="50dp"
android:layout_height="50dp"
app:endColor="#00FF0000"
app:startColor="#FFFF0000"
app:circleThickness="5dp"/>
- app:endColor,尾部颜色
- app:startColor,开始颜色
- app:circleThickness,圆弧宽度
代码
其他具体看代码吧:Loading
-----------------------------目录-----------------------------
- 1、CircleLoadingView
- 2、ThreeBodyLoadingView
网友评论