demo示例
1、定义
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircularProgressView">
<attr name="backgroundCircularColor" format="color" /> <!-- 背景圆环颜色 -->
<attr name="progressCircularColor" format="color" /> <!-- 进度圆环颜色 -->
<attr name="backgroundCircularWidth" format="dimension" /> <!-- 背景圆环宽度 -->
<attr name="progressCircularWidth" format="dimension" /> <!-- 进度圆环宽度 -->
<attr name="radius" format="dimension" /> <!-- 半径 -->
<attr name="progressTextColor" format="color" /> <!-- 进度文字颜色 -->
<attr name="progressTextSize" format="dimension" /> <!-- 进度文字大小 -->
<attr name="max" format="integer" /> <!-- 最大值 -->
<attr name="progress" format="integer" /> <!-- 当前进度 -->
<attr name="isTextDisplayable" format="boolean" /> <!-- 是否显示进度字体 -->
<attr name="style"> <!-- 进度条格式 -->
<enum name="STROKE" value="1000" /> <!-- 空心 -->
<enum name="FILL" value="1001" /> <!-- 实心 -->
</attr>
</declare-styleable>
</resources>
AndroidUtils
public class AndroidUtils {
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
CircularProgressView
public class CircularProgressView extends View {
/**
* mBackgroundCircularColor 背景圆环的颜色
* mProgressCircularColor 进度圆环的颜色
* mBackgroundCircularWidth 背景圆环的宽度
* mProgressCircularWidth 进度圆环的宽度
* mRadius 半径
* mProgressTextColor 进度文字颜色
* mProgressTextSize 进度文字大小
* mMax 最大进度
* mProgress 当前进度
* mIsTextDisplayable 是否显示中间的进度文字
* mStyle 进度条的风格,实心或者空心
*/
private int mBackgroundCircularColor;
private int mProgressCircularColor;
private float mBackgroundCircularWidth;
private float mProgressCircularWidth;
private float mRadius;
private int mProgressTextColor;
private float mProgressTextSize;
private int mMax;
private int mProgress;
private boolean mIsTextDisplayable;
private int mStyle;
/**
* STYLE_STROKE 空心
* STYLE_FILL 实心
*/
public static final int STYLE_STROKE = 1000;
public static final int STYLE_FILL = 1001;
/**
* 构造函数 - 1个参数
*
* @param context
*/
public CircularProgressView(Context context) {
super(context, null);
}
/**
* 构造函数 - 2个参数
*
* @param context
* @param attrs
*/
public CircularProgressView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs, 0);
}
/**
* 构造函数 - 3个参数
*
* @param context
* @param attrs
* @param defStyleAttr
*/
public CircularProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//获取自定义属性和默认值
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircularProgressView);
initByAttributes(attributes, context);
attributes.recycle();
}
/**
* 获取自定义属性和默认值
*
* @param attributes
*/
public void initByAttributes(TypedArray attributes, Context context) {
mBackgroundCircularColor = attributes.getColor(R.styleable.CircularProgressView_backgroundCircularColor, context.getColor(R.color.gray));
mProgressCircularColor = attributes.getColor(R.styleable.CircularProgressView_progressCircularColor, context.getColor(R.color.green));
mBackgroundCircularWidth = attributes.getDimension(R.styleable.CircularProgressView_backgroundCircularWidth, AndroidUtils.dp2px(context, 30));
mProgressCircularWidth = attributes.getDimension(R.styleable.CircularProgressView_backgroundCircularWidth, AndroidUtils.dp2px(context, 20));
mRadius = attributes.getDimension(R.styleable.CircularProgressView_radius, AndroidUtils.dp2px(context, 100));
mProgressTextColor = attributes.getColor(R.styleable.CircularProgressView_progressTextColor, context.getColor(R.color.blue));
mProgressTextSize = attributes.getDimension(R.styleable.CircularProgressView_progressTextSize, AndroidUtils.dp2px(context, 40));
mMax = attributes.getInteger(R.styleable.CircularProgressView_max, 100);
mProgress = attributes.getInteger(R.styleable.CircularProgressView_progress, 25);
mIsTextDisplayable = attributes.getBoolean(R.styleable.CircularProgressView_isTextDisplayable, true);
mStyle = attributes.getInt(R.styleable.CircularProgressView_style, STYLE_STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//计算圆心位置和半径
int center_x = getWidth() / 2; //圆形 x 坐标
//画背景圆环
Paint backgroundCircularPaint = new Paint();
backgroundCircularPaint.setColor(mBackgroundCircularColor); //圆环颜色
switch (mStyle) {
case STYLE_STROKE:
backgroundCircularPaint.setStyle(Paint.Style.STROKE); //空心
backgroundCircularPaint.setStrokeWidth(mBackgroundCircularWidth); //圆环宽度
break;
case STYLE_FILL:
backgroundCircularPaint.setStyle(Paint.Style.FILL); //实心
break;
}
backgroundCircularPaint.setAntiAlias(true); //消除锯齿
canvas.drawCircle(center_x, center_x, mRadius, backgroundCircularPaint); //画出圆环
//画进度圆环
Paint progressCircularPaint = new Paint();
progressCircularPaint.setColor(mProgressCircularColor);
@SuppressLint("DrawAllocation") RectF oval = new RectF(center_x - mRadius, center_x - mRadius, center_x + mRadius, center_x + mRadius);
switch (mStyle) {
case STYLE_STROKE:
progressCircularPaint.setStyle(Paint.Style.STROKE); //空心
progressCircularPaint.setStrokeWidth(mProgressCircularWidth);
canvas.drawArc(oval, -90, 360 * mProgress / mMax, false, progressCircularPaint);
break;
case STYLE_FILL:
progressCircularPaint.setStyle(Paint.Style.FILL_AND_STROKE);
if (mProgress != 0) {
canvas.drawArc(oval, -90, 360 * mProgress / mMax, true, progressCircularPaint);
}
break;
}
//画进度文字
if (mIsTextDisplayable) {
Paint progressTextPaint = new Paint();
progressTextPaint.setColor(mProgressTextColor);
progressTextPaint.setTextSize(mProgressTextSize);
progressTextPaint.setStrokeWidth(5);
progressTextPaint.setTypeface(Typeface.DEFAULT);
int percent = (int) (((float) mProgress / mMax) * 100);
float textWidth = progressTextPaint.measureText(percent + "%"); //测量字体宽度,我们需要根据字体的宽度设置在圆环中间
canvas.drawText(percent + "%", center_x - textWidth / 2, center_x + mProgressTextSize / 2, progressTextPaint);
}
}
/**
* 获取进度最大值
*
* @return
*/
public synchronized int getMax() {
return mMax;
}
/**
* 设置进度最大值
*
* @param mMax
*/
public synchronized void setMax(int mMax) {
if (mMax < 0) {
throw new IllegalArgumentException("max should not less than 0");
}
this.mMax = mMax;
}
/**
* 获取进度
*
* @return
*/
public synchronized int getProgress() {
return mProgress;
}
/**
* 设置进度
*
* @param mProgress
*/
public void setProgress(int mProgress) {
if (mProgress < 0) {
throw new IllegalArgumentException("progress should not less than 0");
}
if (mProgress > mMax) {
mProgress = mMax;
}
if (mProgress <= mMax) {
this.mProgress = mProgress;
postInvalidate();
}
}
public int getBackgroundCircularColor() {
return mBackgroundCircularColor;
}
public void setBackgroundCircularColor(int mBackgroundCircularColor) {
this.mBackgroundCircularColor = mBackgroundCircularColor;
}
public int getProgressCircularColor() {
return mProgressCircularColor;
}
public void setProgressCircularColor(int mProgressCircularColor) {
this.mProgressCircularColor = mProgressCircularColor;
}
public float getBackgroundCircularWidth() {
return mBackgroundCircularWidth;
}
public void setBackgroundCircularWidth(float mBackgroundCircularWidth) {
this.mBackgroundCircularWidth = mBackgroundCircularWidth;
}
public float getProgressCircularWidth() {
return mProgressCircularWidth;
}
public void setProgressCircularWidth(float mProgressCircularWidth) {
this.mProgressCircularWidth = mProgressCircularWidth;
}
public float getRadius() {
return mRadius;
}
public void setRadius(float mRadius) {
this.mRadius = mRadius;
}
public int getProgressTextColor() {
return mProgressTextColor;
}
public void setProgressTextColor(int mProgressTextColor) {
this.mProgressTextColor = mProgressTextColor;
}
public float getProgressTextSize() {
return mProgressTextSize;
}
public void setProgressTextSize(float mProgressTextSize) {
this.mProgressTextSize = mProgressTextSize;
}
public boolean isIsTextDisplayable() {
return mIsTextDisplayable;
}
public void setIsTextDisplayable(boolean mIsTextDisplayable) {
this.mIsTextDisplayable = mIsTextDisplayable;
}
public int getStyle() {
return mStyle;
}
public void setStyle(int mStyle) {
this.mStyle = mStyle;
}
}
2、使用
act_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ViewActivity">
<com.example.circularprogressview_zlz.CircularProgressView
android:id="@+id/id_circular_progress_stroke"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:layout_margin="20dp" />
<com.example.circularprogressview_zlz.CircularProgressView
android:id="@+id/id_circular_progress_fill"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:layout_margin="20dp" />
</LinearLayout>
ViewActivity
public class ViewActivity extends AppCompatActivity {
private CircularProgressView mCircularProgressViewStroke;
private CircularProgressView mCircularProgressViewFill;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_view);
//空心
initStrokeCircularProgressView();
//实心
initFillCircularProgressView();
}
/**
* 空心
*/
private void initStrokeCircularProgressView() {
mCircularProgressViewStroke = findViewById(R.id.id_circular_progress_stroke);
//圆环
mCircularProgressViewStroke.setStyle(CircularProgressView.STYLE_STROKE);
mCircularProgressViewStroke.setBackgroundCircularColor(getColor(R.color.black));
mCircularProgressViewStroke.setProgressCircularColor(getColor(R.color.orange));
mCircularProgressViewStroke.setBackgroundCircularWidth(AndroidUtils.dp2px(this, 40));
mCircularProgressViewStroke.setProgressCircularWidth(AndroidUtils.dp2px(this, 20));
mCircularProgressViewStroke.setRadius(AndroidUtils.dp2px(this, 80));
//文字
mCircularProgressViewStroke.setIsTextDisplayable(true);
mCircularProgressViewStroke.setProgressTextColor(getColor(R.color.blue));
mCircularProgressViewStroke.setProgressTextSize(AndroidUtils.dp2px(this, 20));
//进度
mCircularProgressViewStroke.setMax(100);
mCircularProgressViewStroke.setProgress(88);
}
/**
* 实心
*/
private void initFillCircularProgressView() {
mCircularProgressViewFill = findViewById(R.id.id_circular_progress_fill);
//圆环
mCircularProgressViewFill.setStyle(CircularProgressView.STYLE_FILL);
mCircularProgressViewFill.setBackgroundCircularColor(getColor(R.color.gray));
mCircularProgressViewFill.setProgressCircularColor(getColor(R.color.green));
mCircularProgressViewFill.setRadius(AndroidUtils.dp2px(this, 100));
//文字
mCircularProgressViewFill.setIsTextDisplayable(true);
mCircularProgressViewFill.setProgressTextColor(getColor(R.color.white));
mCircularProgressViewFill.setProgressTextSize(AndroidUtils.dp2px(this, 20));
//进度
mCircularProgressViewFill.setMax(100);
mCircularProgressViewFill.setProgress(44);
}
}