在項(xiàng)目開發(fā)中都會(huì)涉及到網(wǎng)絡(luò)加載,文件上傳或者下載升酣,都會(huì)用到顯示當(dāng)前加載進(jìn)度的進(jìn)度條效果幻工,最近剛好學(xué)了下自定義進(jìn)度條,效果如下:
上面效果的實(shí)現(xiàn)還是通過(guò)自定義view效五,通過(guò)onMeasure()方法測(cè)量地消,onDraw()方法繪制實(shí)現(xiàn)的,一共涉及到三個(gè)東西的繪制畏妖,內(nèi)圓(藍(lán)色圓)脉执、外圓(黃色圓)、中間文字的繪制戒劫,繪制完這些就可以實(shí)現(xiàn)大致效果了半夷;不過(guò)還是跟之前幾篇自定view播客一樣婆廊,在繪制之前需要初始化自定義屬性和畫筆;
初始化定義屬性:
//初始化屬性
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ProgressBar);
mInnerBackground = array.getColor(R.styleable.ProgressBar_innerBackground, mInnerBackground);
mOutterBackground = array.getColor(R.styleable.ProgressBar_outterBackground, mOutterBackground);
mProgressTextColor = array.getColor(R.styleable.ProgressBar_progressTextColor, mProgressTextColor);
mProgressTextSize = array.getDimensionPixelSize(R.styleable.ProgressBar_progressTextSize, sp2px(mProgressTextSize));
mRoundWidth = (int) array.getDimension(R.styleable.ProgressBar_roundWidth, dip2px(mRoundWidth));
array.recycle();
初始化畫筆:
/**
* 根據(jù)繪制的顏色獲取畫筆
* @param color
*/
private Paint getPaint(int color){
Paint paint=new Paint();
paint.setAntiAlias(true);
paint.setColor(color);
paint.setStrokeWidth(mRoundWidth);
paint.setStyle(Paint.Style.STROKE);
return paint;
}
初始化完成后巫橄,就在onMeasure()方法中進(jìn)行測(cè)量淘邻;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
//寬高不一致時(shí)區(qū)最小值
width = Math.min(width, height);
height = Math.min(width, height);
setMeasuredDimension(width, height);
}
為了保證寬高一致使用Math.min(width, height)方法取最小值,這里直接用三元運(yùn)算符也可以湘换,其實(shí)Math.min(width, height)方法也是用的是三元運(yùn)算符進(jìn)行計(jì)算的宾舅;
Math.min(width, height)方法源碼:
* @param a an argument.
* @param b another argument.
* @return the smaller of {@code a} and {@code b}.
*/
public static int min(int a, int b) {
return (a <= b) ? a : b;
}
接下來(lái)進(jìn)行繪制:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int center = getWidth() / 2;
//先繪制內(nèi)圓
canvas.drawCircle(center, center, center - mRoundWidth / 2, mInnerPaint);
//繪制外圓 畫圓弧
if (mMax == 0) {
return;
}
RectF rectf = new RectF(0 + mRoundWidth / 2, 0 + mRoundWidth / 2, getWidth() - mRoundWidth / 2, getHeight() - mRoundWidth / 2);
float preProgree = (float) mCurrentProgress / mMax;
canvas.drawArc(rectf, 0, preProgree * 360, false, mOutterPaint);
//繪制進(jìn)度文字
String text = ((int)(preProgree * 100)) + "%";
Rect rect = new Rect();
textPaint.getTextBounds(text, 0, text.length(), rect);
int x = getWidth() / 2 - rect.width() / 2;
Paint.FontMetricsInt metricsInt = textPaint.getFontMetricsInt();
int dy = (metricsInt.bottom - metricsInt.top) / 2 - metricsInt.bottom;
int baseLine = getHeight() / 2 + dy;
canvas.drawText(text, x, baseLine, textPaint);
}
繪制外圓的時(shí)候需要注意,外圓調(diào)用的不是canvas.drawCircle()方法彩倚,而是調(diào)用canvas.drawArc()繪制圓弧的方法進(jìn)行繪制筹我,這樣效果就繪制完成了;接著又簡(jiǎn)單實(shí)現(xiàn)了下仿58的一個(gè)數(shù)據(jù)加載的效果帆离;
這里就只實(shí)現(xiàn)了圓崎溃,正方形,正三角的一個(gè)切換效果盯质,這個(gè)效果也是采用繪制實(shí)現(xiàn)的袁串;在繪制的時(shí)候要定義一個(gè)變量用來(lái)表明當(dāng)前繪制的是哪個(gè)圖形;
public enum Shape {
Circle, Square, Triangle
}
這里用枚舉來(lái)控制當(dāng)前應(yīng)該繪制哪個(gè)圖形呼巷;同時(shí)在繪制完一個(gè)圖形后還要改變當(dāng)前的這個(gè)狀態(tài)值囱修;比如,繪制完圓王悍,就要將狀態(tài)改成正方形破镰,繪制完正方形,就要將狀態(tài)改成正三角压储,一直這樣循環(huán)的去繪制鲜漩;
/**
* 改變當(dāng)前繪制的狀態(tài)
*/
public void exchange() {
switch (mCurrentShape) {
case Circle:
mCurrentShape = Shape.Square;
break;
case Square:
mCurrentShape = Shape.Triangle;
break;
case Triangle:
mCurrentShape = Shape.Circle;
break;
}
//進(jìn)行繪制
invalidate();
}
調(diào)用invalidate();最終就會(huì)去調(diào)用onDraw();方法進(jìn)行繪制;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (mCurrentShape) {
case Circle:
//畫圓形
int center = getWidth() / 2;
mPaint.setColor(mCircleColor);
canvas.drawCircle(center, center, center, mPaint);
break;
case Square:
//畫正方形
mPaint.setColor(mSquareColor);
canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
break;
case Triangle:
//畫三角形 繪制路線
mPaint.setColor(mTriangleColor);
if (mPath == null) {
mPath = new Path();
mPath.moveTo(getWidth() / 2, 0);
mPath.lineTo(0, (float) (getWidth() / 2 * Math.sqrt(3)));
mPath.lineTo(getWidth(), (float) (getWidth() / 2 * Math.sqrt(3)));
// path.lineTo(getWidth()/2,0);
//將繪制的路徑閉合
mPath.close();
}
canvas.drawPath(mPath, mPaint);
break;
}
}
繪制圓或者正方形的時(shí)候調(diào)用相應(yīng)的方法就可以進(jìn)行繪制了集惋,對(duì)于三角形的繪制并沒(méi)有提供相應(yīng)的方法孕似,就要采用繪制路線的方式進(jìn)行繪制,
從A點(diǎn)繪制到B點(diǎn)刮刑,從B點(diǎn)繪制到C點(diǎn)喉祭,從C點(diǎn)繪制到A點(diǎn)就可以了;從C點(diǎn)繪制到A點(diǎn)的時(shí)候雷绢,不采用這種方式也可以泛烙,從B點(diǎn)繪制到C點(diǎn)后直接調(diào)用mPath.close();方法將繪制路線閉合就可以了;因?yàn)橐L制的是等邊三角形翘紊,在繪制的時(shí)候就要注意高度并不是getHeight();了蔽氨,這里就要用到正弦這些東西來(lái)計(jì)算了,繪制的寬度是知道的,還是getWidth()鹉究,角度也知道中捆,計(jì)算出高度就可以繪制了,繪制完成后坊饶,運(yùn)行下就可以了泄伪。
源碼地址:http://pan.baidu.com/s/1i587fnv