package com.llf.basemodel.recycleview; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PathMeasure; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.View; import android.view.animation.LinearInterpolator; /** * Created by llf on 2017/1/5. * 底部加载转圈的view */ public class LoadingView extends View { private static final String TAG = LoadingView.class.getSimpleName(); private int width, height; private float radius; private Paint mPaint; private Path mPath, dst; private int circleWidth; private PathMeasure mPathMeasure; private float mAnimatorValue = 0; private ValueAnimator mValueAnimator;//属性动画 public LoadingView(Context context) { this(context, null); } public LoadingView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); circleWidth = dpTpPx(4); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setStrokeWidth(circleWidth); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.parseColor("#ffff4444")); mPaint.setStrokeCap(Paint.Cap.ROUND); mPath = new Path(); dst = new Path(); mPathMeasure = new PathMeasure(); mValueAnimator = ValueAnimator.ofFloat(0, 1); mValueAnimator.setDuration(1200); mValueAnimator.setInterpolator(new LinearInterpolator()); mValueAnimator.setRepeatMode(ValueAnimator.RESTART); mValueAnimator.setRepeatCount(ValueAnimator.INFINITE); mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mAnimatorValue = (float) animation.getAnimatedValue(); invalidate(); } }); mValueAnimator.start(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int resultWidth = 500; int resultHeight = 500; if (widthMode == MeasureSpec.EXACTLY) { resultWidth = widthSize; } else { resultWidth = Math.min(resultWidth, widthSize); } if (heightMode == MeasureSpec.EXACTLY) { resultHeight = heightSize; } else { resultHeight = Math.min(resultHeight, heightSize); } setMeasuredDimension(resultWidth, resultHeight); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { width = w; height = h; radius = Math.min(w, h) / 2; mPath.addCircle(width / 2, height / 2, radius - circleWidth, Path.Direction.CCW); super.onSizeChanged(w, h, oldw, oldh); } @Override protected void onDraw(Canvas canvas) { dst.reset(); mPathMeasure.setPath(mPath, false); float stop = mPathMeasure.getLength() * mAnimatorValue; float start = (float) (stop - ((0.5 - Math.abs(mAnimatorValue - 0.5)) * 200f)); mPathMeasure.getSegment(start, stop, dst, true); canvas.drawPath(dst, mPaint); } private int dpTpPx(float value) { DisplayMetrics dm = getResources().getDisplayMetrics(); return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, dm) + 0.5); } }