前言
自定義View作為安卓開發(fā)進(jìn)階必備的一個(gè)技能盾剩,其中不乏一些套路吭净,當(dāng)然更多的是相關(guān)Api的熟練使用以及一些數(shù)學(xué)計(jì)算陌选。學(xué)而時(shí)習(xí)之理郑,多學(xué)習(xí)多模仿,希望能更好的掌握自定義View的使用咨油。
先看下我們要實(shí)現(xiàn)的效果, 主要是進(jìn)度條和文字的更新
要鞏固掌握的知識(shí)點(diǎn)
自定義view的步驟和流程
Paint畫筆的使用您炉,畫圓弧,畫文字役电,文字基線的確定
屬性動(dòng)畫的使用
效果實(shí)現(xiàn)分析
自定義屬性:軌道圓弧的寬度和顏色赚爵,進(jìn)度圓弧的顏色,文字的大小和顏色
用畫筆繪制軌道圓弧法瑟,指定起始角度和結(jié)束角度
用畫筆繪制進(jìn)度圓弧冀膝,注意其sweepAngle是用屬性動(dòng)畫更新的一個(gè)變量實(shí)現(xiàn)動(dòng)畫效果
用畫筆繪制內(nèi)部文字,注意文字的y坐標(biāo)是基線位置
提供設(shè)置最大進(jìn)度和當(dāng)前進(jìn)度的方法給使用者調(diào)用
代碼實(shí)現(xiàn)
- 定義自定義屬性
<declare-styleable name="ProgressView">
<!-- 軌道顏色 -->
<attr name="trackColor" format="color" />
<!-- 軌道寬度 -->
<attr name="trackWidth" format="dimension" />
<!-- 進(jìn)度條顏色 -->
<attr name="progressColor" format="color" />
<!-- 文字顏色 -->
<attr name="progressTextColor" format="color" />
<!-- 文字大小 -->
<attr name="progressTextSize" format="dimension" />
</declare-styleable>
- 初始化軌道霎挟、進(jìn)度圓弧和文字畫筆
//軌道畫筆
mTrackPaint = new Paint();
mTrackPaint.setColor(mTrackColor);
mTrackPaint.setAntiAlias(true);
mTrackPaint.setStrokeWidth(mTrackWidth);
mTrackPaint.setStyle(Paint.Style.STROKE);
mTrackPaint.setStrokeCap(Paint.Cap.ROUND);
//進(jìn)度條畫筆
mProgressPaint = new Paint();
mProgressPaint.setColor(mProgressColor);
mProgressPaint.setAntiAlias(true);
mProgressPaint.setStrokeWidth(mTrackWidth);
mProgressPaint.setStyle(Paint.Style.STROKE);
mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
//文字畫筆
mTextPaint = new Paint();
mTextPaint.setTextSize(mProgressTextSize);
mTextPaint.setColor(mProgressTextColor);
mTextPaint.setAntiAlias(true);
-
在onDraw()方法中繪制 軌道圓弧窝剖、進(jìn)度條圓弧、進(jìn)度文字
- 進(jìn)度條圓弧sweepAngle的計(jì)算 = 軌道的圓弧的角度 * (當(dāng)前更新的進(jìn)度 / 總進(jìn)度)
- 畫文字時(shí)酥夭,y坐標(biāo)是基線高度赐纱,如果直接給定控件高度的一半脊奋。則畫出來的文字會(huì)偏上,這里要計(jì)算基線高度
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//控件中心位置
int center = getWidth() / 2;
//軌道圓弧半徑
int radius = getWidth() / 2 - mTrackWidth / 2;
//畫軌道圓弧
RectF rectF = new RectF(center - radius, center - radius, center + radius, center + radius);
canvas.drawArc(rectF, 135, 270, false, mTrackPaint);
//計(jì)算當(dāng)前進(jìn)度圓弧掃過的角度
float sweepAngle = (mCurrentProgress / mMaxProgress) * 270;
//畫進(jìn)度條圓弧
canvas.drawArc(rectF, 135, sweepAngle, false, mProgressPaint);
//畫文字
String text = (int) mCurrentProgress + "";
Rect rect = new Rect();
mTextPaint.getTextBounds(text, 0, text.length(), rect);
Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
float x = center - rect.width() / 2;
//確定文字繪制的基線高度
float dy = (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom;
float baseline = getHeight() / 2 + dy;
canvas.drawText(text, 0, text.length(), x, baseline, mTextPaint);
}
- 提供設(shè)置當(dāng)前進(jìn)度和最大進(jìn)度的方法
- 使用屬性動(dòng)畫疙描,使記錄當(dāng)前進(jìn)度的局部變量mCurrentProgress的值從0變到設(shè)置的progress诚隙,開始動(dòng)畫。調(diào)用invalidate() 刷新淫痰,使界面不斷重繪以達(dá)到動(dòng)畫的效果
/**
* 設(shè)置當(dāng)前進(jìn)度
* @param progress
*/
public void setCurrentProgress(float progress) {
//屬性動(dòng)畫更新進(jìn)度最楷,刷新界面
ValueAnimator animator = ValueAnimator.ofFloat(0, progress);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mCurrentProgress = (float) valueAnimator.getAnimatedValue();
invalidate();
}
});
animator.setInterpolator(new AccelerateInterpolator());
animator.setDuration(2000);
animator.start();
}
/**
* 設(shè)置最大進(jìn)度
* @param maxProgress
*/
public void setMaxProgress(float maxProgress) {
this.mMaxProgress = maxProgress;
}
- 在Activity中測(cè)試和使用
ProgressView progressView = (ProgressView) findViewById(R.id.progressView);
progressView.setMaxProgress(4000);
progressView.setCurrentProgress(2855);
?項(xiàng)目Github地址:https://github.com/m1Koi/CustomViewPractice
小結(jié)
這個(gè)效果,主要是使用的畫筆繪制圓弧并配合屬性動(dòng)畫更新進(jìn)度的顯示待错。以此類推籽孙,水平進(jìn)度條、圓形進(jìn)度條和App開屏頁(yè)的倒計(jì)時(shí)跳過的效果同樣可以實(shí)現(xiàn)火俄。效果中需要重點(diǎn)掌握和理解的是文字的繪制以及文字基線的定義和計(jì)算犯建。