一、测试截图
文章图片
【android自定义等级评分圆形进度条】二、实现原理
package com.freedomanlib;
import java.util.Timer;
import java.util.TimerTask;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* @name GradeProgressBar
* @Descripation 自定义等级评分圆形进度条,用于设备数据统计页面一键评分
*1、初始化边界宽度、中心坐标和外环、内环半径,各种画笔。
*2、默认最大进度为100,目标进度由用户来指定。
*3、锁定一个内圆环为可点击区域。
*4、点击组件时,调用start()方法启动计时器,重绘界面。
* @author Freedoman
* @date 2014-10-29
* @version 1.0
*/
public class GradeProgressBar extends View { private static final String TAG = "CircleProgressBar";
/**
* 边界宽度、中心坐标和外环、内环半径
*/
private float boundsWidth;
private float centerPoint;
private float overRadius;
private float radius;
/**
* 最大进度、当前进度、是否显示进度文本
*/
private float maxProgress = 100;
private float targetProgress;
private int curProgress;
/**
* 几种画笔
*/
private Paint overRoundPaint;
private Paint roundPaint;
private Paint progressRoundPaint;
private Paint progressTextPaint;
private Paint textPaint;
/**
* 可点击区域的边界
*/
private float clickBoundsLow;
private float clickBoundsHigh;
private onProgressChangedListener listener;
public GradeProgressBar(Context context) {
this(context, null);
} public GradeProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public GradeProgressBar(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.initialize();
} /**
* 初始化
*/
private void initialize() {curProgress = 0;
int whiteColor = Color.rgb(0xF0, 0xF0, 0xF0);
// 外环画笔
overRoundPaint = new Paint();
overRoundPaint.setColor(whiteColor);
overRoundPaint.setStyle(Paint.Style.STROKE);
overRoundPaint.setStrokeWidth(8);
overRoundPaint.setAntiAlias(true);
// 内环画笔
roundPaint = new Paint();
roundPaint.setColor(Color.GRAY);
roundPaint.setStrokeWidth(30);
roundPaint.setStyle(Paint.Style.STROKE);
roundPaint.setAntiAlias(true);
// 进度环画笔(除颜色外同于内环)
progressRoundPaint = new Paint();
progressRoundPaint.setColor(Color.rgb(0xFF, 0x92, 0x24));
progressRoundPaint.setStrokeWidth(20);
progressRoundPaint.setStyle(Paint.Style.STROKE);
roundPaint.setAntiAlias(true);
// 进度文本画笔
progressTextPaint = new Paint();
progressTextPaint.setColor(whiteColor);
progressTextPaint.setStyle(Paint.Style.STROKE);
progressTextPaint.setStrokeWidth(0);
progressTextPaint.setTextSize(80);
progressTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
// 文本画笔
textPaint = new Paint();
textPaint.setColor(whiteColor);
textPaint.setStyle(Paint.Style.STROKE);
textPaint.setStrokeWidth(0);
textPaint.setTextSize(40);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 取当前布局的最短边作为边框的长度
float width = getWidth();
float heigh = getHeight();
boundsWidth = width <= heigh ? width : heigh;
// 中心点
centerPoint = boundsWidth / 2;
// 外环半径
overRadius = centerPoint - 20;
// 内环半径
radius = overRadius - 25;
// 内环所在区域(正方形)锁定为可点击区域
clickBoundsLow = centerPoint - radius;
clickBoundsHigh = centerPoint + radius;
} /**
* 启动进度动画
*/
public void start() {
curProgress = 0;
if (targetProgress == 0) {
targetProgress = 66;
}
final Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
curProgress++;
if (curProgress == targetProgress) {
timer.cancel();
}
postInvalidate();
}
};
timer.schedule(timerTask, 0, 20);
} @SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 外环
canvas.drawCircle(centerPoint, centerPoint, overRadius, overRoundPaint);
// 内环
canvas.drawCircle(centerPoint, centerPoint, radius, roundPaint);
// 进度环
RectF oval = new RectF(centerPoint - radius, centerPoint - radius,
centerPoint + radius, centerPoint + radius);
float curArc = 360 * curProgress / maxProgress;
canvas.drawArc(oval, 0, curArc, false, progressRoundPaint);
// 环中心进度文本
int curPercent = (int) ((curProgress / maxProgress) * 100);
float textWidth = progressTextPaint.measureText(curPercent + "%");
canvas.drawText(curPercent + "%", centerPoint - textWidth / 2,
centerPoint, progressTextPaint);
if (curPercent == 0) {
// 暂未评级
float w = textPaint.measureText("暂未评级");
canvas.drawText("暂未评级", centerPoint - w / 2, centerPoint + 40,
textPaint);
} else if (curPercent < targetProgress) {
// 评级中...
float w = textPaint.measureText("评级中...");
canvas.drawText("评级中...", centerPoint - w / 2, centerPoint + 40,
textPaint);
} else if (curPercent == targetProgress) {
// 评级完成
float w = textPaint.measureText("评级完成");
canvas.drawText("评级完成", centerPoint - w / 2, centerPoint + 40,
textPaint);
}// 对外传递数据
if (listener != null) {
listener.progressChanged(GradeProgressBar.this, curProgress);
}
} public synchronized float getMaxProgress() {
return maxProgress;
} /**
* 设置进度的最大值
*
* @param max
*/
public synchronized void setMaxProgress(float max) {
if (max < 0) {
throw new IllegalArgumentException("max not less than 0");
}
this.maxProgress = max;
} /**
* 获取进度.需要同步
*
* @return
*/
public synchronized float getProgress() {
return targetProgress;
} /**
* 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步 刷新界面调用postInvalidate()能在非UI线程刷新
*
* @param progress
*/
public synchronized void setProgress(float progress) {
if (progress < 0) {
throw new IllegalArgumentException("progress not less than 0");
}
if (progress > maxProgress) {
progress = maxProgress;
}
if (progress <= maxProgress) {
this.targetProgress = progress;
}
} public void setOnProgressChangedListener(onProgressChangedListener listener) {
if (listener == null) {
this.listener = listener;
}
} /**
* 点击评分区域,进行评分
*
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {float x = event.getX();
float y = event.getY();
if (x > clickBoundsLow && x < clickBoundsHigh && y > clickBoundsLow
&& y < clickBoundsHigh) {
start();
}
return super.onTouchEvent(event);
} /**
* @name onProgressChangedListener
* @Descripation 对外接口,提供当前旋转进度
*1、
*2、
* @author Freedoman
* @date 2014-10-29
* @version 1.0
*/
public interface onProgressChangedListener {
public void progressChanged(GradeProgressBar circleProgressBar,
int curProgress);
}
}