最终效果图:
代码:
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);
}
}