1. 概述
我記得QQ之前是有一個,運動步數(shù)的進度效果,今天打開QQ一看發(fā)現(xiàn)沒有了。具體效果我也不清楚了,我就按照自己大概的印象寫一下,這一期我們主要是熟悉Paint畫筆的使用:

2. 效果實現(xiàn)分析
2.1:畫-背景圓弧
2.2:畫-當前進度圓弧
2.3:畫-步數(shù)文字
2.4:提供一些方法
至于什么onMeasure,onDraw,自定義屬性等等我這里就不去介紹了,具體請看這里:
自定義View簡介 - onMeasure,onDraw,自定義屬性
2.1. 畫-背景圓弧
@Override
protected void onDraw(Canvas canvas) {
// 2.畫背景大圓弧
int centerX = mViewWidth / 2;
int centerY = mViewHeight / 2;
// 設(shè)置圓弧畫筆的寬度
mPaint.setStrokeWidth(mRoundWidth);
// 設(shè)置為 ROUND
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeJoin(Paint.Join.ROUND);
// 設(shè)置畫筆顏色
mPaint.setColor(mRoundColor);
mPaint.setStyle(Paint.Style.STROKE);
// 半徑
int radius = (int) (centerX - mRoundWidth);
RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
// 畫背景圓弧
canvas.drawArc(oval, mStartAngle, mSweepAngle, false, mPaint);
}
2.2:畫-當前進度圓弧
// 畫進度圓弧
mPaint.setColor(mProgressColor);
// 計算當前百分比
float percent = (float) mProgressStep/mMaxStep;
// 根據(jù)當前百分比計算圓弧掃描的角度
canvas.drawArc(oval, mStartAngle, percent*mSweepAngle, false, mPaint);
2.3:畫-步數(shù)文字
// 重置畫筆
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setTextSize(mTextSize);
mPaint.setColor(mTextColor);
String mStep = ((int)(percent*mMaxStep)) + "";
// 測量文字的寬高
Rect textBounds = new Rect();
mPaint.getTextBounds(mStep, 0, mStep.length(), textBounds);
int dx = (getWidth() - textBounds.width()) / 2;
// 獲取畫筆的FontMetrics
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
// 計算文字的基線
int baseLine = (int) (getHeight() / 2 + (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom);
// 繪制步數(shù)文字
canvas.drawText(mStep, dx, baseLine, mPaint);
2.4. 提供一些方法
// 設(shè)置當前最大步數(shù)
public synchronized void setMaxStep(int maxStep) {
if (max < 0) {
throw new IllegalArgumentException("max 不能小于0!");
}
this.mMaxStep = maxStep;
}
public synchronized int getMaxStep() {
return mMaxStep;
}
// 設(shè)置進度
public synchronized void setProgress(int progress) {
if (progress < 0) {
throw new IllegalArgumentException("progress 不能小于0!");
}
this.progress = progress;
// 重新刷新繪制 -> onDraw()
invalidate();
}
public synchronized int getProgress() {
return progress;
}
invalidate()為什么會重新調(diào)用onDraw()方法?為什么我們不能在子線程更新UI ? 為何不去看看源碼
3. 請思考
我記得Hongyang寫過一篇打造炫酷的進度條,在慕課網(wǎng)上也有視頻講解,大家可以去看一下,如果你不是很熟悉自定義View,可以自己嘗試去實現(xiàn),效果如下:

58同城數(shù)據(jù)加載效果,有一部分也是Paint畫筆的使用,可以先實現(xiàn)如下效果(一秒鐘切換一次造型,不能用圖片):

所有分享大綱:Android進階之旅 - 自定義View篇