圆形百分比view主要是对canvas的操作以及坐标的计算
/**
* Description:
* - - - - - - - - - - - - - - - - - - -
* Created by HUI on 17/3/20.
* - - - - - - - - - - - - - - - - - - -
* Version 1.0.0
*/
public class CircleProgressView extends View {
private static final int CIRCLE_RADIUS = 360;
private static final int MAX_RADIUS = 300; //外圆半径
private static final int MIN_RADIUS = 280; //内圆半径
private static final float SCALE_SPACE = 3.6f;//刻度之间的间隔-->每3.6度画一格
private int mWidth; //view宽
private int mHeight;//View高
private int centerX; //view中心点 x
private int centerY; //view中心点 y
private int mProgress = -1; //当前进度
private Paint circlePaint;//画圆画笔
private Paint textPaint;//文字画笔
private int defaultProgressColor = Color.parseColor("#bfcabf"); //默认刻度线颜色
private int doneProgressColor = Color.parseColor("#ae850d"); //已完成刻度线颜色
private float progressStrokeWidth = 4.0f; //刻度线宽
private int textSize = 40; //中心文字大小
private int textColor = Color.parseColor("#000000"); //文字颜色
public CircleProgressView(Context context) {
super(context);
init(context, null);
}
public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
//获取自定义属性
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView);
defaultProgressColor = attributes.getColor(R.styleable.CircleProgressView_default_progress_color, Color.parseColor("#bfcabf"));
doneProgressColor = attributes.getColor(R.styleable.CircleProgressView_done_progress_color, Color.parseColor("#ae850d"));
progressStrokeWidth = attributes.getFloat(R.styleable.CircleProgressView_progress_stroke_width, 4.0f);
textSize = attributes.getDimensionPixelSize(R.styleable.CircleProgressView_center_text_size, 40);
textColor = attributes.getColor(R.styleable.CircleProgressView_center_text_color, Color.parseColor("#000000"));
attributes.recycle();
}
//画圆画笔
circlePaint = new Paint();
circlePaint.setColor(defaultProgressColor);
circlePaint.setAntiAlias(true);
circlePaint.setStrokeWidth(progressStrokeWidth);
circlePaint.setStyle(Paint.Style.FILL);
//文字画笔
textPaint = new Paint();
textPaint.setColor(textColor);
textPaint.setAntiAlias(true);
textPaint.setTextSize(textSize);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextAlign(Paint.Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
centerX = mWidth / 2;
centerY = mHeight / 2;
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(final Canvas canvas) {
//①绘制一圈默认刻度
circlePaint.setColor(defaultProgressColor);
drawScale(canvas, CIRCLE_RADIUS, circlePaint);
//②绘制文字
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float top = fontMetrics.top;
float bottom = fontMetrics.bottom;
//重新计算出文字中心点的Y坐标
int textY = (int) (mHeight / 2 - top / 2 - bottom / 2);
//展示进度
canvas.drawText(Math.max(mProgress, 0) + "%", centerX, textY, textPaint);
//③绘制已完成的刻度
circlePaint.setColor(doneProgressColor);
drawScale(canvas, mProgress * SCALE_SPACE, circlePaint);
}
//绘制刻度线
private void drawScale(Canvas canvas, float progress, Paint paint) {
if (progress <= 0) {
return;
}
float degree; //弧度
float startX, startY, endX, endY;
for (float i = 1, j; (j = i * SCALE_SPACE) <= progress ; i++) {
degree = (float) getRadian(j);
//刻度线的长度就是大圆与小圆的半径差
startX = centerX + (float) Math.sin(degree) * MIN_RADIUS;
startY = centerY - (float) Math.cos(degree) * MIN_RADIUS;
endX = centerX + (float) Math.sin(degree) * MAX_RADIUS;
endY = centerY - (float) Math.cos(degree) * MAX_RADIUS;
canvas.drawLine(startX, startY, endX, endY, paint);
}
}
//设置当前已完成进度
public synchronized void setCurrentProgress(final int progress) {
if (progress < 0 || progress > 100) {
throw new RuntimeException("当前进度不合法");
}
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <= progress; i++) {
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
mProgress = i;
postInvalidate();
}
}
}).start();
}
//转化角度
private double getRadian(float i) {
return i * Math.PI / 180;
}
}
</br>
在values文件夹下新建自定义属性文件attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleProgressView">
<!--默认刻度颜色-->
<attr name="default_progress_color" format="color|reference"/>
<!--已完成刻度颜色-->
<attr name="done_progress_color" format="color|reference"/>
<!--刻度线宽度-->
<attr name="progress_stroke_width" format="float"/>
<!--文字大小-->
<attr name="center_text_size" format="dimension"/>
<!--文字颜色-->
<attr name="center_text_color" format="color|reference"/>
</declare-styleable>
</resources>
</br>
在布局中使用该自定义控件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:text="设置进度75"
android:id="@+id/start"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.summer.tree.widget.CircleProgressView
android:id="@+id/cv"
android:layout_marginTop="20dp"
app:default_progress_color="#bfcabf"
app:done_progress_color="#ae850d"
app:center_text_size="20dp"
app:progress_stroke_width="6.0"
app:center_text_color="#0000ff"
android:layout_width="match_parent"
android:layout_height="320dp"/>
</LinearLayout>
在代码中调用setCurrentProgress()方法设置具体进度范围0-100
效果图: