1. 程式人生 > >自定義控制元件之跑步圓環

自定義控制元件之跑步圓環

/**
* @author ex-chenmengjia001
* @date 2018/11/26
* 1.畫外圓弧
* 2.畫內圓弧
* 3.畫文字
* 4.進度屬性動畫
*/
public class QQRunView extends View {

private int mMeasuredWidth;
private int mMeasuredHeight;
private Paint mPaint = new Paint();
private int mRountColor = Color.BLUE;
//圓弧寬度
private int mRoundWidth = 38;
//圓弧進度顏色
private int mProgressColor = Color.RED;
private int mProgressStep = 50;
private int mMaxStep = 100;
private float numberTextSize = 30;
//步數
private String stepNumber = "50";
private int mCenterY;
//當前圓弧長度
private float currentAngleLength = 0;

public QQRunView(Context context) {
this(context, null);
}

public QQRunView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public QQRunView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int Widthmode = MeasureSpec.getMode(widthMeasureSpec);
int heightmode = MeasureSpec.getMode(heightMeasureSpec);
mMeasuredWidth = getMeasuredWidth();
mMeasuredHeight = getMeasuredHeight();
//寬度是wrap_content
if (Widthmode == MeasureSpec.AT_MOST) {
mMeasuredWidth = 600;
widthMeasureSpec= MeasureSpec.makeMeasureSpec(mMeasuredWidth, MeasureSpec.AT_MOST);

}
//高度是wrap_content
if (heightmode == MeasureSpec.AT_MOST) {
mMeasuredHeight = 600;
heightMeasureSpec=MeasureSpec.makeMeasureSpec(mMeasuredHeight, MeasureSpec.AT_MOST);

}

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

}

@Override
protected void onDraw(Canvas canvas) {
//計算中心點
int centerX = mMeasuredWidth / 2;
mCenterY = mMeasuredHeight / 2;
mPaint.setStrokeWidth(mRoundWidth);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setColor(mRountColor);
mPaint.setStyle(Paint.Style.STROKE);
//半徑
int radius = centerX - mRoundWidth;
RectF oval = new RectF(centerX - radius, mCenterY - radius, centerX + radius, mCenterY + radius);
//起始角度
float startAngle = 135;
//結束角度
float sweepAngle = 270;
//畫外圓弧
canvas.drawArc(oval, startAngle, sweepAngle, false, mPaint);
//畫進度圓弧
drawArcProgress(canvas, oval, startAngle, currentAngleLength);
//畫數字
drawTextNumber(canvas, centerX);
//畫文字
drawTextStepString(canvas, centerX);


}

/**
* 畫文字步數
* @param canvas
* @param centerX
*/
private void drawTextStepString(Canvas canvas, int centerX) {
Paint paint = new Paint();
paint.setTextSize(dipToPx(18));
paint.setTextAlign(Paint.Align.CENTER);
paint.setAntiAlias(true);
paint.setColor(getResources().getColor(R.color.colorPrimaryDark));
String stepString = "步數";
Rect rect = new Rect();
paint.getTextBounds(stepString, 0, stepString.length(), rect);
canvas.drawText(stepString, centerX, mCenterY + rect.height() + getFontHeight(dipToPx(26)), paint);

}

public int getFontHeight(float fontSize) {
Paint paint = new Paint();
paint.setTextSize(fontSize);
Rect bounds_Number = new Rect();
paint.getTextBounds(stepNumber, 0, stepNumber.length(), bounds_Number);
return bounds_Number.height();
}

/**
* 畫數字
* @param canvas
* @param centerX
*/
private void drawTextNumber(Canvas canvas, int centerX) {
Paint paint = new Paint();
paint.setTextAlign(Paint.Align.CENTER);
paint.setAntiAlias(true);
paint.setTextSize(dipToPx(26));
Typeface typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
paint.setTypeface(typeface);
Rect rect = new Rect();
paint.getTextBounds(stepNumber, 0, stepNumber.length(), rect);
canvas.drawText(stepNumber, centerX, mCenterY + rect.height() / 2, paint);
}

/**
* 畫進度圓弧
* @param canvas
* @param oval
* @param startAngle
* @param sweepAngle
*/
private void drawArcProgress(Canvas canvas, RectF oval, float startAngle, float sweepAngle) {
Paint paint = new Paint();
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(mRoundWidth);
paint.setColor(mProgressColor);
canvas.drawArc(oval, startAngle, sweepAngle, false, paint);
}

/**
* 開啟圓弧動畫
* @param start
* @param current
* @param length
*/
private void setAnimation(float start, float current, int length) {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(start, current);
valueAnimator.setDuration(length);
valueAnimator.setTarget(currentAngleLength);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentAngleLength = (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.start();
}

/**
* 設定步數
* @param totalStep
* @param currCount
*/
public void setCurrentCount(int totalStep, int currCount) {
stepNumber = currCount + "";
setTextSize(currCount);
if (currCount >= totalStep) {
currCount = totalStep;
}
float percent = (float) (currCount * 1.0 / totalStep);
float sweepAngel = percent * 270;
setAnimation(0, sweepAngel, 3000);

}

public void setTextSize(int num) {
String s = String.valueOf(num);
int length = s.length();
if (length <= 4) {
numberTextSize = dipToPx(50);
} else if (length > 4 && length <= 6) {
numberTextSize = dipToPx(40);
} else if (length > 6 && length <= 8) {
numberTextSize = dipToPx(30);
} else if (length > 8) {
numberTextSize = dipToPx(25);
}
}

private int dipToPx(float dip) {
float density = getContext().getResources().getDisplayMetrics().density;
return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
}


}