一、效果图
二、代码实现
public class LoadingView extends View {
private static final long ANIMATION_TIMEOUT = 1500;
private TextPaint mPaint;
private int mMaxRadius;
private int mDotWidth;
private int mColor = Color.TRANSPARENT;
private AnimatorSet mCircleDotAnimatorSet;
private float[] mDotAngles = null;
public final static int LINE_STYLE_DOT =0;
public final static int LINE_STYLE_ARC =1;
private int mLineStyle = LINE_STYLE_DOT;
public LoadingView(Context context) {
this(context,null);
}
public LoadingView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public LoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint();
}
public void setLineStyle(int mLineStyle) {
this.mLineStyle = mLineStyle;
if(mLineStyle==LINE_STYLE_DOT) {
mDotWidth = (int) dip2px(8);
}else{
mDotWidth = (int) dip2px(3);
}
}
public float dip2px(int dp){
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,getResources().getDisplayMetrics());
}
private void initPaint() {
// 实例化画笔并打开抗锯齿
mPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG );
mPaint.setAntiAlias(true);
mPaint.setPathEffect(new CornerPathEffect(10)); //设置线条类型
mPaint.setStrokeWidth(dip2px(1));
mPaint.setTextSize(dip2px((12)));
mPaint.setStyle(Paint.Style.STROKE);
mDotWidth = (int) dip2px(8);
mColor = Color.BLUE;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mDotAngles = null;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if(widthMode!=MeasureSpec.EXACTLY){
width = (int) dip2px(100);
}
if(heightMode!=MeasureSpec.EXACTLY){
height = (int) dip2px(100);
}
setMeasuredDimension(width,height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
if(width==0 || height==0) return;
int diameter = Math.min(width, height) / 2;
mMaxRadius = diameter - mDotWidth /2;
initPoints();
int storeId = canvas.save();
canvas.translate(width/2,height/2);
if(mLineStyle==LINE_STYLE_DOT) {
drawDotCircle(canvas);
}else{
drawArcCircle(canvas);
}
canvas.restoreToCount(storeId);
}
private void drawArcCircle(Canvas canvas) {
if(mDotAngles==null || mDotAngles.length==0) return;
int firstPointY = (int) (Math.sin(Math.toRadians(mDotAngles[0])) * mMaxRadius);
int firstPointX = (int) (Math.cos(Math.toRadians(mDotAngles[0])) * mMaxRadius);
int lastPointY = (int) (Math.sin(Math.toRadians(mDotAngles[mDotAngles.length-1])) * mMaxRadius);
int lastPointX = (int) (Math.cos(Math.toRadians(mDotAngles[mDotAngles.length-1])) * mMaxRadius);
double lineLenghtPower = Math.pow(firstPointY - lastPointY, 2) + Math.pow(firstPointX - lastPointX, 2);
double length = Math.sqrt(lineLenghtPower)/2f;
float degrees = (float) Math.toDegrees(Math.asin(length / mMaxRadius) ) *2;
drawArcSport(canvas,mDotAngles[mDotAngles.length-1],degrees);
}
private void drawDotCircle(Canvas canvas) {
if(mDotAngles==null) return;
int color = mPaint.getColor();
float strokeWidth = mPaint.getStrokeWidth();
Paint.Cap strokeCap = mPaint.getStrokeCap();
mPaint.setStrokeWidth(mDotWidth);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setColor(argb(255,0,0,255));
for (int i = 0; i< mDotAngles.length; i++){
double dotAngle = mDotAngles[i];
int pointY = (int) (Math.sin(Math.toRadians(dotAngle)) * mMaxRadius);
int pointX = (int) (Math.cos(Math.toRadians(dotAngle)) * mMaxRadius);
canvas.drawPoint(pointX,pointY,mPaint);
}
mPaint.setColor(color);
mPaint.setStrokeWidth(strokeWidth);
mPaint.setStrokeCap(strokeCap);
}
private void initPoints() {
if(mDotAngles !=null && mDotAngles.length==5) return;
mDotAngles = new float[5];
float dotRadius = mDotWidth /2f;
float dotAngle = (float) Math.toDegrees(Math.atan(dotRadius/mMaxRadius)*2);
for (int i = 0; i< mDotAngles.length; i++){
float angle = 360f - (dotAngle+8)*(i+1);
mDotAngles[i] = angle;
}
if(mCircleDotAnimatorSet!=null){
mCircleDotAnimatorSet.cancel();
}
mCircleDotAnimatorSet = buildDotAnimationSet();
mCircleDotAnimatorSet.start();
}
private AnimatorSet buildDotAnimationSet() {
AnimatorSet animatorSet = new AnimatorSet();
Animator[] animators = new Animator[mDotAngles.length];
for (int i=0;i<mDotAngles.length;i++){
Animator animator = buildDotAnimation(mDotAngles[i],i);
animator.setStartDelay(100*i);
animators[i] = animator;
}
animatorSet.playTogether(animators);
return animatorSet;
}
private Animator buildDotAnimation(final float startAngle, final int i) {
ValueAnimator animatorTimer = ValueAnimator.ofFloat(0,1);
animatorTimer.setDuration(ANIMATION_TIMEOUT);
animatorTimer.setRepeatCount(ValueAnimator.INFINITE);
animatorTimer.setInterpolator(new AccelerateDecelerateInterpolator());
animatorTimer.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float fraction = animation.getAnimatedFraction();
float angle = (float) (startAngle + fraction*360);
if(mDotAngles!=null){
mDotAngles[i] = angle;
}
if(i==0){
postInvalidate();
}
}
});
return animatorTimer;
}
public static int argb(
@IntRange(from = 0, to = 255) int alpha,
@IntRange(from = 0, to = 255) int red,
@IntRange(from = 0, to = 255) int green,
@IntRange(from = 0, to = 255) int blue) {
return (alpha << 24) | (red << 16) | (green << 8) | blue;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
try {
if (mCircleDotAnimatorSet != null) {
mCircleDotAnimatorSet.cancel();
}
}catch (Exception e){
e.printStackTrace();
}
}
private void drawArcSport(Canvas canvas,float currentAngle,float sweepAngle) {
int oldColor = mPaint.getColor();
Paint.Style style = mPaint.getStyle();
float strokeWidth = mPaint.getStrokeWidth();
mPaint.setStrokeWidth(mDotWidth);
mPaint.setColor(mColor);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawArc(new RectF(-mMaxRadius,-mMaxRadius,mMaxRadius,mMaxRadius),currentAngle,sweepAngle,false,mPaint);
mPaint.setColor(oldColor);
mPaint.setStyle(style);
mPaint.setStrokeWidth(strokeWidth);
}
}
来源:oschina
链接:https://my.oschina.net/ososchina/blog/3184955