項目中很多時候時候會用到圓形的進度條,Android系統自帶的不太好看,通常我們都會去自定義它,今天我們來介紹一下自定義控件以及自定義屬性的使用。
先來看一下自定義CircleProgress的代碼,如果你看着太喫力,請先閱讀一下《Android 自定義View、ViewGroup(一)之工作原理》
public class CircleProgress extends View {
public static final int STROKE = 0;
public static final int FILL = 1;
private Paint paint;
private int circleColor;
private int progressColor;
private int textColor;
private float textSize;
private float circleWidth;
private int circleMax;
private boolean textIsDisplay;
private int style;
/**
* 當前進度
*/
private int progress;
public CircleProgress(Context context) {
this(context, null);
}
public CircleProgress(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleProgress(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar);
//獲取自定義屬性和默認值
circleColor = mTypedArray.getColor(R.styleable.CircleProgressBar_circle_color, Color.RED);
progressColor = mTypedArray.getColor(R.styleable.CircleProgressBar_circle_progress_color, Color.GREEN);
textColor = mTypedArray.getColor(R.styleable.CircleProgressBar_text_color, Color.GREEN);
textSize = mTypedArray.getDimension(R.styleable.CircleProgressBar_text_size, 15);
circleWidth = mTypedArray.getDimension(R.styleable.CircleProgressBar_circle_width, 5);
circleMax = mTypedArray.getInteger(R.styleable.CircleProgressBar_circle_max, 100);
textIsDisplay = mTypedArray.getBoolean(R.styleable.CircleProgressBar_is_text_display, true);
style = mTypedArray.getInt(R.styleable.CircleProgressBar_style, 0);
mTypedArray.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//1.畫出最外層的大圓環
int center = getWidth()/2;
int radius = (int) (center-circleWidth/2);
paint.setColor(circleColor); //設置圓環的顏色
paint.setStyle(Paint.Style.STROKE); //設置空心
paint.setStrokeWidth(circleWidth); //設置圓環的寬度
paint.setAntiAlias(true); //消除鋸齒
canvas.drawCircle(center, center, radius, paint);
//2.畫百分比
paint.setStrokeWidth(0);
paint.setColor(textColor);
paint.setTextSize(textSize);
paint.setTypeface(Typeface.DEFAULT_BOLD);
int percent = (int) (((float) progress / (float) circleMax) * 100);
float textWidth = paint.measureText(percent + "%");
if (isTextIsDisplay() && percent != 0 && style == STROKE) {
canvas.drawText(percent + "%", center - textWidth / 2, center + textSize / 2, paint);
}
//3.畫進度
paint.setStrokeWidth(circleWidth);
paint.setColor(progressColor);
//用於定義的圓弧的形狀和大小的界限
RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius);
switch (style) {
case STROKE: {
paint.setStyle(Paint.Style.STROKE);
canvas.drawArc(oval, 0, 360 * progress / circleMax, false, paint);
break;
}
case FILL: {
paint.setStyle(Paint.Style.FILL_AND_STROKE);
if (progress != 0)
canvas.drawArc(oval, 0, 360 * progress / circleMax, true, paint);
break;
}
}
}
/**
* 設置進度
* @param progress
*/
public synchronized void setProgress(int progress){
if(progress < 0){
throw new IllegalArgumentException("progress not less than 0");
}
if(progress > circleMax){
progress = circleMax;
}
if(progress <= circleMax){
this.progress = progress;
postInvalidate();
}
}
/**
* 獲取進度
* @return
*/
public synchronized int getProgress(){
return progress;
}
public synchronized int getCircleMax() {
return circleMax;
}
public synchronized void setCircleMax(int circleMax) {
if (circleMax < 0) {
throw new IllegalArgumentException("max not less than 0");
}
this.circleMax = circleMax;
}
public int getCircleColor() {
return circleColor;
}
public void setCircleColor(int circleColor) {
this.circleColor = circleColor;
}
public int getProgressColor() {
return progressColor;
}
public void setProgressColor(int progressColor) {
this.progressColor = progressColor;
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
}
public float getTextSize() {
return textSize;
}
public void setTextSize(float textSize) {
this.textSize = textSize;
}
public float getCircleWidth() {
return circleWidth;
}
public void setCircleWidth(float circleWidth) {
this.circleWidth = circleWidth;
}
public boolean isTextIsDisplay() {
return textIsDisplay;
}
public void setTextIsDisplay(boolean textIsDisplay) {
this.textIsDisplay = textIsDisplay;
}
public int getStyle() {
return style;
}
public void setStyle(int style) {
this.style = style;
}
}
步驟如下:
1. 定義類繼承View重寫構造方法並初始化畫筆Paint
2. 根據Context的obtainStyledAttributes方法獲取屬性集,並獲取自定義屬性和默認值
3. 對外暴露get、set方法,讓外部可以設置和獲取指定值
4.重寫onDraw方法畫出大圓環、百分比和進度
如果想了解更多自定義進度條,請點擊