1.效果
2效果分析
底部是一个圆形(空心圆)
上面是一个弧形(根据角度来确定弧度的大小)
里面是一个TextView
3.代码实现
3.1 创建自定义CMProgressView
public class CMProgressView extends View {
public CMProgressView(Context context) {
this(context,null);
}
public CMProgressView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public CMProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
3.2创建自定义属性
在values目录下的attrs.xml文件中创建自定义属性
<declare-styleable name="CMProgressView">
<attr name="cmProgressOuterColor" format="color"></attr>
<attr name="cmProgressInnerColor" format="color"></attr>
<attr name="cmProgressBorderWidth" format="dimension"></attr>
<attr name="cmProgressTextSize" format="dimension"></attr>
<attr name="cmProgressTextColor" format="color"></attr>
</declare-styleable>
3.3 在布局文件中使用
<com.test.cmviewdemo.CMProgressView
android:id="@+id/main_cmProgress_cmProgressView"
android:layout_margin="10dp"
android:padding="10dp"
app:cmProgressBorderWidth="10dp"
app:cmProgressInnerColor="@color/colorAccent"
app:cmProgressOuterColor="@color/colorPrimary"
app:cmProgressTextColor="@color/colorAccent"
app:cmProgressTextSize="20sp"
android:layout_width="100dp"
android:layout_height="100dp" />
3.4 获取自定义属性
//获取自定义属性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CMProgressView);
cmProgressOuterColr = typedArray.getColor(R.styleable.CMProgressView_cmProgressOuterColor, cmProgressOuterColr);
cmProgressInnerColor = typedArray.getColor(R.styleable.CMProgressView_cmProgressInnerColor, cmProgressInnerColor);
cmProgressBorderWidth = typedArray.getDimensionPixelOffset(R.styleable.CMProgressView_cmProgressBorderWidth,cmProgressBorderWidth);
cmProgressTextColor = typedArray.getColor(R.styleable.CMProgressView_cmProgressTextColor,cmProgressTextColor);
cmProgressTextSize = typedArray.getDimensionPixelSize(R.styleable.CMProgressView_cmProgressTextSize,cmProgressTextSize);
typedArray.recycle();
3.5 创建画笔
private Paint cmProgressOuterPaint,cmProgressInnerPaint,cmProgressTextPaint;
//初始化画笔
cmProgressOuterPaint = new Paint();
cmProgressOuterPaint.setAntiAlias(true);
cmProgressOuterPaint.setColor(cmProgressOuterColr);
cmProgressOuterPaint.setStrokeWidth(cmProgressBorderWidth);
cmProgressOuterPaint.setStyle(Paint.Style.STROKE);
cmProgressOuterPaint.setStrokeCap(Paint.Cap.ROUND);
cmProgressInnerPaint = new Paint();
cmProgressInnerPaint.setAntiAlias(true);
cmProgressInnerPaint.setColor(cmProgressInnerColor);
cmProgressInnerPaint.setStrokeWidth(cmProgressBorderWidth);
cmProgressInnerPaint.setStyle(Paint.Style.STROKE);
cmProgressInnerPaint.setStrokeCap(Paint.Cap.ROUND);
cmProgressTextPaint = new Paint();
cmProgressTextPaint.setAntiAlias(true);
cmProgressTextPaint.setTextSize(cmProgressTextSize);
cmProgressTextPaint.setColor(cmProgressTextColor);
3.6 从写onMeasure()方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//从新测量 宽高,如果是AT_MOST 模式,则赋默认值
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if(MeasureSpec.AT_MOST == widthMode){
width = 40;
}
if(MeasureSpec.AT_MOST == heightMode){
height = 40;
}
width = (height > width ? width : height);
height = (height > width ? width : height);
//设置宽高
setMeasuredDimension(width,height);
}
3.7 重写onDray()方法
@Override
protected void onDraw(Canvas canvas) {
//1.画内圆弧
canvas.drawCircle(getWidth()/2,getWidth()/2,getWidth()/2-cmProgressBorderWidth/2,cmProgressOuterPaint);
//2.画外圆弧
RectF rectF = new RectF(0+cmProgressBorderWidth/2,0+cmProgressBorderWidth/2,getWidth()-cmProgressBorderWidth/2,getHeight()-cmProgressBorderWidth/2);
float precent = (float)cmProgressCurrent/cmProgressMax;
canvas.drawArc(rectF,0,precent*360,false,cmProgressInnerPaint);
//3.画进度文字
String text = String.valueOf((int)(precent*100))+"%";
//找基线
Rect textBounds = new Rect();
cmProgressTextPaint.getTextBounds(text,0,text.length(),textBounds);
int dx = getWidth()/2 - textBounds.width()/2;
int dy = (textBounds.bottom - textBounds.top)/2 - textBounds.bottom;
int baseLine = getHeight()/2 + dy;
canvas.drawText(text,dx,baseLine,cmProgressTextPaint);
}
3.8 提供方法,供外部调用者使用
public synchronized void setProgressMas(int max){
if(0 > max){
throw new IllegalArgumentException("最大值需大于0");
}
this.cmProgressMax = max;
}
public synchronized void setProgressCurrent(int current){
if( cmProgressMax < current){
throw new IllegalArgumentException("当前进度需小于最大值");
}
this.cmProgressCurrent = current;
invalidate();
}
3.9 外部调用
private void initProgressView() {
Button main_progress_bt = findViewById(R.id.main_cmProgress_start_bt);
final CMProgressView main_progress_cmProgressView = findViewById(R.id.main_cmProgress_cmProgressView);
main_progress_cmProgressView.setProgressMas(150);
main_progress_bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 90);
valueAnimator.setDuration(2000);
valueAnimator.setInterpolator(new DecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float animatedValue = (float) animation.getAnimatedValue();
main_progress_cmProgressView.setProgressCurrent((int) animatedValue);
}
});
valueAnimator.start();
}
});
}
Github Demo
https://github.com/hualianrensheng/CMViewDemo