/
LoadingCircleView.java
133 lines (109 loc) · 4.33 KB
/
LoadingCircleView.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package com.mario.library.view;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
public class LoadingCircleView extends View {
private Path path;
private PathMeasure pathMeasure;
private Path dst; // 被截取的路径
private Paint mPaint; // 画笔
// View的宽高
private int height;
private int width;
private float radius; // 空心圆的半径
private float mLength; // path路径的长度
ValueAnimator valueAnimator; // 属性动画
private float mAnimatorValue; // 属性动画返回的百分比
private float stop; // 截取路径时的stopD值
private float start; // 截取路径时的startD值
public LoadingCircleView(Context context) {
this(context,null);
}
public LoadingCircleView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public LoadingCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
radius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 21, getContext().getResources().getDisplayMetrics()); // 初始化半径
path = new Path();
dst = new Path();
mPaint = new Paint();
pathMeasure = new PathMeasure();
// 设置画笔属性
mPaint.setAntiAlias(true);
mPaint.setColor(0xbfe46d32);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3.5f, getContext().getResources().getDisplayMetrics()));
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
// 勾勒空心圆
path.reset();
path.addCircle(width / 2, height / 2, radius, Path.Direction.CW);
// 生成pathMeasure对象
pathMeasure.setPath(path, true);
// 获取path的长度
mLength = pathMeasure.getLength();
// 通过属性动画取得百分比值,并更新View
valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 获取动画进行的百分比
mAnimatorValue = (float) animation.getAnimatedValue();
postInvalidate(); // 更新界面
}
});
// 设置动画的属性
valueAnimator.setDuration(2100);
valueAnimator.setRepeatCount(1000);
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//为加强动画效果,每次对画布旋转不同角度
canvas.rotate(360.0f * mAnimatorValue - 45.0f, width / 2, height / 2);
//初始化截取的路径
dst.reset();
dst.lineTo(0, 0); // 消除硬件加速的影响
// 更新截取的开始值和结束值:当mAnimatorValue为0或1时,两个值相等
stop = mAnimatorValue * mLength;
start = (float) (stop - ((0.5 - Math.abs(mAnimatorValue - 0.5)) * mLength));
// 截取路径后,并绘制路径
pathMeasure.getSegment(start, stop, dst, true);
canvas.drawPath(dst, mPaint);
// canvas.translate(width/2,height/2);
// Path mPath = new Path();
// Path mDst = new Path();
// PathMeasure mPathMeasure = new PathMeasure();
//// 顺时针画 半径为400px的圆
// mPath.addCircle(0,0, 400, Path.Direction.CW);
// mPathMeasure.setPath(mPath, false);
//
//// 画直线
// mDst.moveTo(110, 0);
// mDst.lineTo(200, 300);
//
//// 截取 0.25 到 0.5 距离的圆弧放置dst中
// mPathMeasure.getSegment(mPathMeasure.getLength() * 0.25f,
// mPathMeasure.getLength() * 0.5f,
// mDst,
// true);
// canvas.drawPath(mDst, paint);
}
}