直接上代碼,做個學習筆記好了。
/**
* Created by Jimbray .
* on 2016/7/12
* Email: jimbray16@gmail.com
* Description: 這是我第一個真正意義上的自定義View
*/
public class MyFirstProgressbar extends View {
//max progress 雖然注釋寫了,但是還是不解釋
private int mMaxProgress = 100;
// current progress
private int mCurrentProgress;
//progress bar 背景顏色
private int mBackgroundColor;
//progress bar 進度條顏色
private int mProgressColor;
//progress bar 進度條高度
private float mProgressBarheight;
//progress bar 背景高度
private float mBackgroundHeight;
//設置默認值
//默認progress bar 背景顏色
private final int default_background_color = Color.rgb(204, 204, 204);
//默認progress bar 進度條顏色
private final int default_progressbar_color = Color.rgb(66, 145, 241);
//默認 pregress bar 背景高度
private float default_background_height;
//默認 porgress 進度條高度
private float default_progressbar_height;
//默認progress bar 背景寬度(最小寬度)
private final float default_background_width = dp2px(45.f);
//畫筆
private Paint mBackgroundPaint, mProgressbarPaint;
//progress 需要draw 的矩形區域
private RectF mBackgroundRectF = new RectF(0, 0, 0, 0);
private RectF mProgressbarRectF = new RectF(0, 0, 0, 0);
public MyFirstProgressbar(Context context) {
super(context);
init(context, null, 0);
}
public MyFirstProgressbar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public MyFirstProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
default_background_height = dp2px(1.0f);
default_progressbar_height = dp2px(1.5f);
//progress bar 背景高度 比 progress bar 進度條高度 矮啊
//都是用默認值,沒有把這些數值拋出去做屬性
mBackgroundHeight = default_background_height;
mProgressBarheight = default_progressbar_height;
mBackgroundColor = default_background_color;
mProgressColor = default_progressbar_color;
initPainters();
}
/**
* 初始化 畫筆 Paint
*/
private void initPainters() {
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setColor(mBackgroundColor);
mProgressbarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mProgressbarPaint.setColor(mProgressColor);
}
/**
* 重載 函數
* @return view 的推薦最小寬度
* 修改為 progress bar 背景的默認高度
*/
@Override
protected int getSuggestedMinimumWidth() {
return (int) default_background_width;
}
/**
* 重載 函數
* @return view 的推薦最小高度
* 修改為 progress bar 的默認高度 (娶個最高的吧,不然高的那個頭被截掉了就不好了)
*/
@Override
protected int getSuggestedMinimumHeight() {
return Math.max((int) mBackgroundHeight, (int) mProgressBarheight);
}
/**
* 這個函數的 解析 Google 一大把,就不解釋了
* @param widthMeasureSpec
* @param heightMeasureSpec
* 現在這里是個套路活,跟著老司機走就行了
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));
}
/**
* 測量 view 的 寬高信息
* @param measureSpec
* @param isWidth
* @return
*/
private int measure(int measureSpec, boolean isWidth) {
int result;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
//不要忘記 padding ,萬一有人設置了呢
int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
if (mode == MeasureSpec.EXACTLY) { //如果 width 或者 height 都設置了 精確值:比如 45dp啊什么的
result = size; //就按主人的來吧,誒,森么是主人
} else {
//其他情況,既然你都不知道要什么,就按我的套路來吧
result = isWidth ? getSuggestedMinimumWidth() : getSuggestedMinimumHeight();
result += padding; //padding 這個小伙子還是很調皮的
if (mode == MeasureSpec.AT_MOST) {
if (isWidth) {
result = Math.max(result, size);
} else {
result = Math.min(result, size);
}
}
}
return result;
}
/** 要開車了,快上車!
* @param canvas
*/
@Override
protected synchronized void onDraw(Canvas canvas) {
calRectF();
canvas.drawRect(mBackgroundRectF, mBackgroundPaint);
canvas.drawRect(mProgressbarRectF, mProgressbarPaint);
}
/**
* 精華就在這里了。
* 一開始我也看不懂
* 現在我也看不懂
* 可是效果出來了
* 就這么滴吧
* 多看幾次
* 說不定就懂了呢
*/
private void calRectF() {
mProgressbarRectF.left = getPaddingLeft();
mProgressbarRectF.top = getHeight() / 2.0f - mProgressBarheight / 2.0f;
mProgressbarRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() + getPaddingLeft();
mProgressbarRectF.bottom = getHeight() / 2.0f + mProgressBarheight / 2.0f ;
mBackgroundRectF.left = mProgressbarRectF.right;
mBackgroundRectF.top = getHeight() / 2.0f - mBackgroundHeight / 2.0f;
mBackgroundRectF.right = getWidth() - getPaddingRight();
mBackgroundRectF.bottom = getHeight() / 2.0f + mBackgroundHeight / 2.0f;
}
/** 這個我也不想說
* 如果三個月之后我看不懂這個代碼
* 說明
* 我應該是失憶了
* @return
*/
public int getProgress() {
return mCurrentProgress;
}
/**
* 同上
* @return
*/
public int getMax() {
return mMaxProgress;
}
/**
* 同上
* @param progress
*/
public void setProgress(int progress) {
mCurrentProgress = progress;
invalidate();
}
/**
* 讓我的 progress 動起來!
* ValueAnimator 是個神器
* Google一下
* @param progress
*/
public void anitProgress(int progress) {
ValueAnimator animator = ValueAnimator.ofInt(0, progress);
animator.setDuration(1500);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentProgress = (int) animation.getAnimatedValue();
postInvalidate();
}
});
animator.start();
}
public float dp2px(float dp) {
final float scale = getResources().getDisplayMetrics().density;
return dp * scale + 0.5f;
}
這就是我第一個實質意義上的自定義View了,以前一般都是擴展TextView啊,組合LinearLayout
之類的。
雖然這個View也是看著別人的代碼寫的。
不過總算是自己動手敲出來了。
敲開心啊。
我 照抄學習的 project 代碼家的NumberProgressBar
已發布到