一个最基础的自定义View 圆形进度条,可设置背景色、进度条颜色(渐变色)下载进度控制;可二次定制度高;
核心代码:
@Override
protected void onDraw(@NonNull Canvas canvas) {
super.onDraw(canvas);
int mW = getMeasuredWidth();
int mH = getMeasuredHeight();
int centerX = mW/2;
int centerY = mH/2;
Log.i(TAG, "onDraw: "+mW +"-" +mH);
//画背景色
canvas.save();
paintBg.setColor(backgroundColor);
RectF rectBg = new RectF(strokeWidth,strokeWidth,mW-strokeWidth,mH-strokeWidth);
canvas.drawArc(rectBg,0,360,false , paintBg);
//画进度条颜色
float ratio = (float) Math.min(progress / max , 1.00);
paint.setColor(loadingColor); //设置进度条颜色
// SweepGradient sweepGradient = new SweepGradient(centerX , centerY , new int[]{loadingColor , Color.YELLOW} , null);
// paint.setShader(sweepGradient); //设置进度条渐变色
paint.setStrokeCap(Paint.Cap.ROUND); 设置画笔边缘为半圆状
canvas.drawArc(rectBg,0,360*ratio,false , paint);
canvas.restore();
//画中间的文案
paintText.setTextSize(dp2px(18));
paintText.setColor(Color.BLACK);
paintText.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = paintText.getFontMetrics();
float disY = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
canvas.drawText(progress+"%" , centerX , centerY+disY , paintText);
}
全部代码:
package com.cuichen.mytestdemo.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.cuichen.mytestdemo.R;
public class CircleProgressView extends View {
private final String TAG = CircleProgressView.class.getSimpleName();
public CircleProgressView(Context context) {
super(context);
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initAttrs(attrs);
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(attrs);
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initAttrs(attrs);
}
private void initAttrs( @Nullable AttributeSet attrs){
TypedArray typedArray = getContext().obtainStyledAttributes(attrs , R.styleable.CircleProgress);
try{
backgroundColor = typedArray.getColor(R.styleable.CircleProgress_backgroundColorCircle , Color.parseColor("#5503DAC5"));
loadingColor = typedArray.getColor(R.styleable.CircleProgress_progressColorCircle ,Color.parseColor("#FF018786"));
strokeWidth = (int) typedArray.getDimension(R.styleable.CircleProgress_strokeWidthCircle , 18);
max = typedArray.getInt(R.styleable.CircleProgress_maxCircle , 100);
progress = typedArray.getInt(R.styleable.CircleProgress_progressCircle , 50);
}catch (Exception e){
typedArray.recycle();
}
}
private int strokeWidth = 18;
private float progress = 0f;
private float max = 100f;
private int backgroundColor;
private int loadingColor;
final int DEFAULT_HEIGHT_DP = 66;
Paint paintBg , paint , paintText;
void init(){
paintBg = new Paint();
paintBg.setAntiAlias(true);
paintBg.setStyle(Paint.Style.STROKE);
paintBg.setStrokeWidth(strokeWidth);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
paintText = new Paint();
paintText.setAntiAlias(true);
}
public void setProgress(int progress){
this.progress = progress;
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.i(TAG, "onMeasure: ");
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
int height = 0;
switch (heightSpecMode){
case MeasureSpec.AT_MOST:
height = dp2px(DEFAULT_HEIGHT_DP);
break;
case MeasureSpec.EXACTLY:
case MeasureSpec.UNSPECIFIED:
height = heightSpecSize;
break;
}
setMeasuredDimension(widthSpecSize, height);
if(paint == null) {
init();
}
}
//RectF
//left:左边坐标;在绘制中常表示为起点的Y轴坐标
//top:上边左边;在绘制中常表示为起点的X轴坐标
//right:右边坐标;在绘制中常表示为终点的X轴坐标
//bottom:下边坐标;在绘制中常表示为终点的Y轴坐标
@Override
protected void onDraw(@NonNull Canvas canvas) {
super.onDraw(canvas);
int mW = getMeasuredWidth();
int mH = getMeasuredHeight();
int centerX = mW/2;
int centerY = mH/2;
Log.i(TAG, "onDraw: "+mW +"-" +mH);
//画背景色
canvas.save();
paintBg.setColor(backgroundColor);
RectF rectBg = new RectF(strokeWidth,strokeWidth,mW-strokeWidth,mH-strokeWidth);
canvas.drawArc(rectBg,0,360,false , paintBg);
//画进度条颜色
float ratio = (float) Math.min(progress / max , 1.00);
paint.setColor(loadingColor); //设置进度条颜色
// SweepGradient sweepGradient = new SweepGradient(centerX , centerY , new int[]{loadingColor , Color.YELLOW} , null);
// paint.setShader(sweepGradient); //设置进度条渐变色
paint.setStrokeCap(Paint.Cap.ROUND); 设置画笔边缘为半圆状
canvas.drawArc(rectBg,0,360*ratio,false , paint);
canvas.restore();
//画中间的文案
paintText.setTextSize(dp2px(18));
paintText.setColor(Color.BLACK);
paintText.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = paintText.getFontMetrics();
float disY = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
canvas.drawText(progress+"%" , centerX , centerY+disY , paintText);
}
private int dp2px(int dp){
float density = getContext().getResources().getDisplayMetrics().density;
return (int) (dp * density);
}
}
<declare-styleable name="CircleProgress">
<attr name="backgroundColorCircle" format="color"/>
<attr name="progressColorCircle" format="color"/>
<attr name="strokeWidthCircle" format="dimension"/>
<attr name="maxCircle" format="integer"/>
<attr name="progressCircle" format="integer"/>
</declare-styleable>