最进在学自定义View,我还是一只菜鸟,今天就做一个自定义View的圆环进度条,话不多说,先上效果图
直接贴代码吧
package rxjava.application.com.rxjavaproject;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
/**
* @author Qiujc
* created time at 2016/05/20
*/
public class LoadingView extends View {
private Paint circlePaint; //背景圆环画笔
private Paint progressPaint; //进度条圆环画笔
private Paint mTextPaint;//数字画笔
private int currentProgress = 0; //当前进度
private float radius; // 圆的半径
private int circleColor = Color.GRAY;
private int progressColor = Color.parseColor("#E78018");
private int mtextColor = Color.BLACK;
private float circlePaintWith;
private Context mContext;
private int SrceenWidth;
private int SrceenHeight;
private float mTextWidth;
private float mTextHeight;
private int progressRoundColor = Color.BLUE;
private int maxProgress = 100;
private float progressWith;
public LoadingView(Context context) {
super(context);
mContext = context;
init(null, 0);
}
public LoadingView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init(attrs, 0);
}
public LoadingView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
init(attrs, defStyle);
}
private void init(AttributeSet attrs, int defStyle) {
circlePaintWith = dp2Px(15);
progressWith = dp2Px(15);
radius = dp2Px(100);
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(circleColor);
circlePaint.setStrokeWidth(circlePaintWith);
circlePaint.setStyle(Paint.Style.STROKE);
progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
progressPaint.setColor(progressColor);
progressPaint.setStrokeWidth(progressWith);
progressPaint.setStyle(Paint.Style.STROKE);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setColor(mtextColor);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextWidth = mTextPaint.measureText(String.valueOf(currentProgress) + "%");
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
mTextHeight = fontMetrics.bottom;
mTextPaint.setTextSize(dp2Px(30));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float circleX = SrceenWidth / 2.0f;
float circleY = SrceenHeight / 2.0f;
//先绘制背景圆环
canvas.drawCircle(SrceenWidth / 2, SrceenHeight / 2, radius, circlePaint);
//再绘制进度数字
canvas.drawText(String.valueOf(currentProgress + "%"), SrceenWidth / 2, SrceenHeight / 2 + (mTextHeight), mTextPaint);
RectF rect = new RectF(0, 0, 0, 0);
float circleRealRadius = radius + circlePaintWith;
float dmax = (progressWith - circlePaintWith) / 2.0f;
//rect的上下左右分别代表,进度条圆环最外围的坐标
rect.left = circleX - circleRealRadius + circlePaintWith;
rect.right = circleX + circleRealRadius - circlePaintWith;
rect.top = circleY - circleRealRadius + circlePaintWith;
rect.bottom = circleY + circleRealRadius - circlePaintWith;
float currentAngle = (float) 360 * currentProgress / (float) maxProgress;
//绘制出当前进度条
canvas.drawArc(rect, -90, currentAngle, false, progressPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
SrceenWidth = measureWidth(widthMeasureSpec);
SrceenHeight = measureHeight(heightMeasureSpec);
}
private int measureWidth(int widthMeasureSpec) {
int result;
int mode = MeasureSpec.getMode(widthMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
int padding = getPaddingLeft() + getPaddingRight();
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
result = getSuggestedMinimumHeight();
result += padding;
if (mode == MeasureSpec.AT_MOST) {
result = Math.max(result, size);
}
}
return result;
}
private int measureHeight(int heightMeasureSpec) {
int result;
int mode = MeasureSpec.getMode(heightMeasureSpec);
int size = MeasureSpec.getSize(heightMeasureSpec);
int padding = getPaddingTop() + getPaddingBottom();
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
result = getSuggestedMinimumHeight();
result += padding;
if (mode == MeasureSpec.AT_MOST) {
result = Math.max(result, size);
}
}
return result;
}
/**
* 数据转换: dp---->px
*/
private float dp2Px(float dp) {
return dp * getContext().getResources().getDisplayMetrics().density;
}
/**
* 设置当前进度
* @param progress
* progress (0 - 100)
*/
public void setProgress(int progress) {
if (progress > maxProgress) {
progress = maxProgress;
} else if (progress < 0) {
progress = 0;
}
this.currentProgress = progress;
invalidate();
}
/**
* 设置背景圆环颜色
*
* @param color
*/
public void setBackCircleColor(int color) {
this.circleColor = color;
circlePaint.setColor(color);
}
/**
* 设置背景圆环宽度
*/
public void setBackCircleWith(int width) {
this.circlePaintWith = width;
circlePaint.setStrokeWidth(width);
}
/**
* 设置进度条圆环颜色
*
* @param color
*/
public void setProgressColor(int color) {
this.progressColor = color;
progressPaint.setColor(color);
}
/**
* 设置进度条圆环宽度
*/
public void setProgressWith(int width) {
this.progressWith = width;
progressPaint.setStrokeWidth(width);
}
}
使用的时候可以配合Hanlder来使用,实时的去更新这个view,调用它的setProgress方法(注意progress的范围是在0-100之间),类似下载,我们应该先计算好当前进度在传入这个view中就好了。