最終效果圖:
程式碼:
public class PointerLoadingView extends View {
/**
* 外圈圓心寬度
*/
private int ringWidth = dip2px(6);
/**
* 圓心和圓環的顏色
*/
private int primaryColor = Color.parseColor("#4b546a");
/**
* 指標的顏色
*/
private int pointerColor = Color.parseColor("#70c7d4");
/**
* 大圓心半徑
*/
private int bigCircleRadius = dip2px(10);
/**
* 小圓心的半徑
*/
private int smallCircleRadius = dip2px(5);
/**
* 指標轉動角度
*/
private int pointerAngle = 0;
/**
* 圓弧的轉動半徑
*/
private int arcAngle = 45;
/**
* 正方形控制元件的尺寸
*/
private int mSquareSize;
public PointerLoadingView(Context context) {
super(context);
init();
}
public PointerLoadingView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PointerLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
Paint bigCirclePaint;
Paint smallCirclePaint;
Paint ringPaint;
Paint pointerPaint;
Paint arcPaint;
Path path;
private void init() {
//大圓心畫筆
bigCirclePaint = new Paint();
bigCirclePaint.setAntiAlias(true);
bigCirclePaint.setColor(pointerColor);
//小圓心畫筆
smallCirclePaint = new Paint();
smallCirclePaint.setAntiAlias(true);
smallCirclePaint.setColor(primaryColor);
//圓環畫筆
ringPaint = new Paint();
ringPaint.setAntiAlias(true);
ringPaint.setStyle(Paint.Style.STROKE);
ringPaint.setStrokeWidth(ringWidth);
ringPaint.setColor(primaryColor);
//圓弧畫筆
arcPaint = new Paint();
arcPaint.setAntiAlias(true);
arcPaint.setStyle(Paint.Style.STROKE);
arcPaint.setStrokeWidth(ringWidth);
arcPaint.setStrokeCap(Paint.Cap.ROUND);
arcPaint.setColor(pointerColor);
//指標畫筆
pointerPaint = new Paint();
pointerPaint.setAntiAlias(true);
pointerPaint.setStyle(Paint.Style.FILL);
pointerPaint.setColor(pointerColor);
path = new Path();
}
/**
* 動畫是否在播放
*/
private boolean animPlaying = false;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mSquareSize == 0) return;
canvas.save();
//畫三角指標
canvas.translate(mSquareSize / 2, mSquareSize / 2);
canvas.rotate(pointerAngle);
path.moveTo(-smallCircleRadius - 1, 0);
path.lineTo(0, -mSquareSize / 2 + 15);
path.lineTo(smallCircleRadius + 1, 0);
canvas.drawPath(path, pointerPaint);
//畫大圓心
canvas.drawCircle(0, 0, bigCircleRadius, bigCirclePaint);
//畫圓環
canvas.drawCircle(0, 0, mSquareSize / 2 - 10, ringPaint);
//畫小圓心
canvas.drawCircle(0, 0, smallCircleRadius, smallCirclePaint);
//畫圓弧
RectF rectF = new RectF(-mSquareSize / 2 + 10, -mSquareSize / 2 + 10, mSquareSize / 2 - 10, mSquareSize / 2 - 10);
canvas.drawArc(rectF, 270, arcAngle, false, arcPaint);
//合併畫布
canvas.restore();
if (!animPlaying)
startAnim();
}
private void startAnim() {
final ValueAnimator animator = ValueAnimator.ofInt(1);
animator.setDuration(1000);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
animPlaying = true;
}
@Override
public void onAnimationEnd(Animator animator) {
animPlaying = false;
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float fraction = animator.getAnimatedFraction();
pointerAngle = (int) (360.0f * fraction);
if (fraction <= 0.25)
arcAngle = (int) (fraction * 240);
else if (0.25 < fraction && fraction <= 0.75)
arcAngle = (int) (-240 * fraction + 120);
else arcAngle = (int) (240 * fraction - 240);
Log.i("TAG", arcAngle + ":fraction:" + fraction);
invalidate();
}
});
animator.start();
}
public int dip2px(float dpValue) {
final float scale = Resources.getSystem().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mSquareSize = w;
Log.i(getClass().getSimpleName(), "w:" + w + ",h:" + h);
}
}
複製程式碼