package com.team.zhuoke.ui.loadplay;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import com.team.zhuoke.R;
import java.lang.ref.WeakReference;
/**
* Created by tiandawu on 2017/1/9.
*/
public class LoadingView extends View {
private int mOuterCircleRadius;
private int mOuterCircleColor;
private int mInnerTriangleRadius;
private int mInnerTriangleColor;
private int mBackgroundColor;
private int mStrokeWidth;
private boolean mIsNeedBackground;
private Paint mPaint;
private Paint mTrianglePaint;
private Paint mBackGroundPaint;
private boolean isReverse = false;
private int mProgress = 0;
private int mStartAngle = -90;
private int mRotateAngle = 0;
private int mDel = 30;
private RectF mRectF;
private RectF mRoundRectF;
private Path mPath;
private PointF mRotateCenter;
private MyHandler mHandler;
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);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LoadingView);
mOuterCircleRadius = typedArray.getDimensionPixelSize(R.styleable.LoadingView_outerCircleRadius, 50);
mOuterCircleColor = typedArray.getColor(R.styleable.LoadingView_outerCircleColor, 0xFF228B22);
mInnerTriangleRadius = typedArray.getDimensionPixelSize(R.styleable.LoadingView_innerTriangleRadius, 25);
mInnerTriangleColor = typedArray.getColor(R.styleable.LoadingView_innerTriangleColor, 0xFF228B22);
mIsNeedBackground = typedArray.getBoolean(R.styleable.LoadingView_isNeedBackground, true);
mBackgroundColor = typedArray.getColor(R.styleable.LoadingView_backgroundColor, 0xBB222222);
mStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.LoadingView_strokeWidth, 5);
typedArray.recycle();
init();
}
private void init() {
//设置画进度圈的画笔
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(mOuterCircleColor);
mPaint.setStrokeWidth(mStrokeWidth);
mPaint.setStyle(Paint.Style.STROKE);
//设置画三角形的画笔
mTrianglePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTrianglePaint.setColor(mInnerTriangleColor);
//设置画背景的画笔
mBackGroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBackGroundPaint.setColor(mBackgroundColor);
mPath = new Path();
mRotateCenter = new PointF();
mRoundRectF = new RectF();
mHandler = new MyHandler(this);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//判断外圆的半径
mOuterCircleRadius = (int) (Math.min(mOuterCircleRadius,
(Math.min(w - getPaddingRight() - getPaddingLeft(), h - getPaddingTop() - getPaddingBottom()) - 4 * mPaint.getStrokeWidth()) / 2));
if (mOuterCircleRadius < 0) {
mStrokeWidth = Math.min(w - getPaddingRight() - getPaddingLeft(), h - getPaddingTop() - getPaddingBottom()) / 2;
mOuterCircleRadius = Math.min(w - getPaddingRight() - getPaddingLeft(), h - getPaddingTop() - getPaddingBottom()) / 4;
}
float left = (w - 2 * mOuterCircleRadius) / 2;
float top = (h - 2 * mOuterCircleRadius) / 2;
float diameter = 2 * mOuterCircleRadius;
mRectF = new RectF(left, top, left + diameter, top + diameter);
//判断内圆的半径大小
mInnerTriangleRadius = (mInnerTriangleRadius < mOuterCircleRadius) ? mInnerTriangleRadius : 3 * mOuterCircleRadius / 5;
if (mInnerTriangleRadius < 0) {
mInnerTriangleRadius = 0;
}
//计算内圆的圆心,圆心应该和外圆圆心相同
float centerX = left + mOuterCircleRadius;
float centerY = top + mOuterCircleRadius;
//计算内圆的内接三角形的三个定点组成的path
mPath.moveTo(centerX - mInnerTriangleRadius / 2, (float) (centerY - Math.sqrt(3) * mInnerTriangleRadius / 2));
mPath.lineTo(centerX + mInnerTriangleRadius, centerY);
mPath.lineTo(centerX - mInnerTriangleRadius / 2, (float) (centerY + Math.sqrt(3) * mInnerTriangleRadius / 2));
mPath.close();
mRotateCenter.set(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
mRoundRectF.left = 0;
mRoundRectF.top = 0;
mRoundRectF.right = w;
mRoundRectF.bottom = h;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureSize(widthMeasureSpec, 140), measureSize(heightMeasureSpec, 140));
}
private int measureSize(int measureSpec, int defaultSize) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
int resultSize = defaultSize;
switch (specMode) {
case MeasureSpec.EXACTLY:
resultSize = specSize;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
resultSize = Math.min(specSize, resultSize);
break;
}
return resultSize;
}
@Override
protected void onDraw(Canvas canvas) {
if (mIsNeedBackground) {
canvas.drawRoundRect(mRoundRectF, 8, 8, mBackGroundPaint);
}
if (isReverse) {
mProgress -= mDel;
mStartAngle += mDel;
if (mStartAngle >= 270) {
mStartAngle = -90;
isReverse = false;
}
mRotateAngle += mDel;
if (mRotateAngle >= 360) {
mRotateAngle = 0;
}
canvas.save();
canvas.rotate(mRotateAngle, mRotateCenter.x, mRotateCenter.y);
canvas.drawPath(mPath, mTrianglePaint);
canvas.restore();
} else {
mProgress += mDel;
if (mProgress >= 360) {
isReverse = true;
}
canvas.drawPath(mPath, mTrianglePaint);
}
canvas.drawArc(mRectF, mStartAngle, mProgress, false, mPaint);
mHandler.sendEmptyMessageDelayed(mHandler.REFRESH_VIEW, 80);
}
private static class MyHandler extends Handler {
public static final int REFRESH_VIEW = 0;
private final WeakReference<LoadingView> mLoadingViewWeakReference;
public MyHandler(LoadingView loadingView) {
mLoadingViewWeakReference = new WeakReference<LoadingView>(loadingView);
}
@Override
public void handleMessage(Message msg) {
if (mLoadingViewWeakReference.get() != null) {
switch (msg.what) {
case REFRESH_VIEW:
mLoadingViewWeakReference.get().postInvalidate();
break;
}
}
}
}
}