自定义圆形进度条,见下图:

1、自定义进度条类:
package com.example.msh.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.example.msh.mshaliapp.R;
/**
* 自定义圆形进度条
* Author:William(徐威)
* Create Time:2018-08-15
*/
public class PercentCircle extends View {
//全局变量
private Paint mTextPaint;
private Paint mBackgroundPaint;
private Paint mRingPaint;
private int mCircleX;
private int mCircleY;
private float mCurrentAngle;
private RectF mArcRectF;
private float mStartSweepValue;
private int mTargetPercent;
private int mCurrentPercent;
private int mDefaultRadius = 60;
private int mRadius;
private int mDefaultBackgroundColor = 0xffafb4db;
private int mBackgroundColor;
private int mDefaultRingColor = 0xff6950a1;
private int mRingColor;
private int mDefaultTextSize;
private int mTextSize;
private int mDefaultTextColor = 0xffffffff;
private int mTextColor;
private int progressRate = 1000;
/**
* 构造函数
* Author:William(徐威)
* Create Time:2018-08-15
*
* @param context
*/
public PercentCircle(Context context) {
super(context);
init(context);
}
/**
* 设置进度条的进度频率(微妙)
* Author:William(徐威)
* Create Time:2018-08-15
*
* @param rate (多少微妙前进1个百分比)
*/
public void setProgressRate(int rate) {
progressRate = rate;
}
public PercentCircle(Context context, AttributeSet attrs) {
super(context, attrs);
// 自定义属性,attrs
// 使用TypedArray
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PercentageRing);
// 背景圆的半径
mRadius = typedArray.getInt(R.styleable.PercentageRing_radius, mDefaultRadius);
// 背景圆的颜色
mBackgroundColor = typedArray.getColor(R.styleable.PercentageRing_circleBackground, mDefaultBackgroundColor);
// 文字的颜色 默认白色
mTextColor = typedArray.getColor(R.styleable.PercentageRing_textColor, mDefaultTextColor);
// 外圆环的颜色
mRingColor = typedArray.getColor(R.styleable.PercentageRing_ringColor, mDefaultRingColor);
typedArray.recycle();
init(context);
}
public PercentCircle(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
/**
* 初始化
* Author:William(徐威)
* Create Time:2018-08-15
* @param context
*/
private void init(Context context) {
//圆环开始角度 -90° 正北方向
mStartSweepValue = -90;
//当前角度
mCurrentAngle = 0;
//当前百分比
mCurrentPercent = 0;
//设置中心园的画笔
mBackgroundPaint = new Paint();
mBackgroundPaint.setAntiAlias(true);
mBackgroundPaint.setColor(mBackgroundColor);
mBackgroundPaint.setStyle(Paint.Style.FILL);
//设置文字的画笔
mTextPaint = new Paint();
mTextPaint.setColor(mTextColor);
mTextPaint.setAntiAlias(true);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setStrokeWidth((int) (0.025 * mRadius));
mTextPaint.setTextSize(mRadius / 2); //文字大小为半径的一半
mTextPaint.setTextAlign(Paint.Align.CENTER);
//设置外圆环的画笔
mRingPaint = new Paint();
mRingPaint.setAntiAlias(true);
mRingPaint.setColor(mRingColor);
mRingPaint.setStyle(Paint.Style.STROKE);
mRingPaint.setStrokeWidth((float) (0.075 * mRadius));
//获得文字的字号 因为要设置文字在圆的中心位置
mTextSize = (int) mTextPaint.getTextSize();
}
// 主要是测量wrap_content时候的宽和高,因为宽高一样,只需要测量一次宽即可,高等于宽
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measure(widthMeasureSpec), measure(widthMeasureSpec));
}
// 当wrap_content的时候,view的大小根据半径大小改变,但最大不会超过屏幕
private int measure(int measureSpec) {
int result = 0;
/**
* 1、先获取测量模式 和 测量大小
* 2、如果测量模式是MatchParent 或者精确值,则宽为测量的宽
* 3、如果测量模式是WrapContent ,则宽为 直径值 与 测量宽中的较小值;否则当直径大于测量宽时,会绘制到屏幕之外;
*/
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = (int) (mRadius * 2 + mRingPaint.getStrokeWidth() * 2);
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
/**
* 实现View布局
* Author:William(徐威)
* Create Time:2018-08-15
* @param changed
* @param left
* @param top
* @param right
* @param bottom
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
/**
* 1、如果半径大于圆心的横坐标,需要手动缩小半径的值,否则画到屏幕之外;
* 2、改变了半径,则需要重新设置字体大小;
* 3、改变了半径,则需要重新设置外圆环的宽度
* 4、画背景圆的外接矩形,用来画圆环;
*/
mCircleX = getMeasuredWidth() / 2;
mCircleY = getMeasuredHeight() / 2;
if (mRadius > mCircleX) {
mRadius = mCircleX;
mRadius = (int) (mCircleX - 0.075 * mRadius);
mTextPaint.setStrokeWidth((float) (0.025 * mRadius));
mTextPaint.setTextSize(mRadius / 2);
mRingPaint.setStrokeWidth((float) (0.075 * mRadius));
mTextSize = (int) mTextPaint.getTextSize();
}
mArcRectF = new RectF(mCircleX - mRadius, mCircleY - mRadius, mCircleX + mRadius, mCircleY + mRadius);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 1、画中间背景圆
* 2、画文字
* 3、画圆环
* 4、判断进度,重新绘制
*/
canvas.drawCircle(mCircleX, mCircleY, mRadius, mBackgroundPaint);
canvas.drawText(String.valueOf(mCurrentPercent) + "%", mCircleX, mCircleY + mTextSize / 4, mTextPaint);
canvas.drawArc(mArcRectF, mStartSweepValue, mCurrentAngle, false, mRingPaint);
if (mCurrentPercent < mTargetPercent) {
//当前百分比+1
mCurrentPercent += 1;
//当前角度+360
mCurrentAngle += 3.6;
//按照设置的前进频率毫秒数重画一次(默认1000ms)
postInvalidateDelayed(progressRate);
}
}
/**
* 设置最大百分比
* Author:William(徐威)
* Create Time:2018-08-15
* @param targetPercent
*/
public void setTargetPercent(int targetPercent) {
mTargetPercent = targetPercent;
}
}
2、前端UI页面Xml文件布局引入:
<LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="350dp"
android:gravity="center"
android:minHeight="25px"
android:minWidth="25px"
android:orientation="horizontal">
<com.example.msh.view.PercentCircle
android:id="@+id/pCircleBar"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerInParent="true"
app:circleBackground="#F39800"
app:radius="250"
app:ringColor="#73B347"
app:textColor="#ffffff" />
</LinearLayout>
3、Activity后台操作:
PercentCircle pCircleBar = (PercentCircle) findViewById(R.id.pCircleBar);
pCircleBar.setProgressRate(120);//设置进度条前进频率,单位微妙,此处是120微妙前进1%
pCircleBar.setTargetPercent(100);//设置进度条最大可以到达的百分比,此处设置是到达100%
781

被折叠的 条评论
为什么被折叠?



