这个也算是已经写过的例子了,整理了一下就拿出来了,参考了一篇文章,并在原有的基础上优化了圆环上下段之间的衔接间隔问题,时间久远,找不到文章的地址了,如果有帮忙找到,请联系我加上去,谢谢.
public class CircleRingView extends View {
private static final String TAG = "SleepRingView";
private int[] mColors;
private Paint circlePaint; //表盘外轮廓画笔
private Paint linePaint; // 表盘内短线画笔
private int mWidth;
private int mHeight;
private float startPercent = 0;
private float initStartPercent;
//圆环的画笔
private Paint cyclePaint;
//圆的直径
private float mRadius = 300;
//圆的粗细
private float mStrokeWidth = 80;
private List<CircleRingMode> ringModes = new ArrayList<>();
private Context mContext;
private int startY = 0;
private ArgbEvaluator argbEvaluator = new ArgbEvaluator();//颜色渐变插值器
private int radius;
public CircleRingView(Context context) {
this(context, null);
}
public CircleRingView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
mColors = new int[]{
context.getResources().getColor(R.color.colorSleepGradient2),
context.getResources().getColor(R.color.colorSleepGradient3),
context.getResources().getColor(R.color.colorSleepGradient),
context.getResources().getColor(R.color.colorSleepGradient4)
};
initPaint();
}
/**
* 创建所有的paint
*/
private void initPaint() {
int strokeWidth = UnitUtil.dp2px(mContext, 2.5f);
circlePaint = getAvailablePaint(Color.BLUE, strokeWidth, Paint.Style.STROKE);
linePaint = getAvailablePaint(mContext.getResources().getColor(R.color.colorSleepGradient), strokeWidth, Paint.Style.FILL);
linePaint.setTextSize(UnitUtil.dp2px(getContext(), 12));
mStrokeWidth = UnitUtil.dp2px(mContext, 24);
cyclePaint = getAvailablePaint(Color.BLUE, (int) mStrokeWidth, Paint.Style.STROKE);
startY = UnitUtil.dp2px(mContext, 10);
}
private Paint getAvailablePaint(int color, int strokeWidth, Paint.Style style) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FAKE_BOLD_TEXT_FLAG);
paint.setAntiAlias(true);
paint.setColor(color);
paint.setStyle(style);
paint.setStrokeWidth(strokeWidth);
paint.setDither(true);//设置图像抖动处理
paint.setStrokeJoin(Paint.Join.ROUND);//画笔线等连接处的轮廓样式
paint.setSubpixelText(true);
return paint;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
circlePaint.setShader(new LinearGradient(3, 3, mWidth - 3, mHeight - 3, mColors, null, Shader.TileMode.CLAMP));
canvas.drawCircle(mWidth / 2, mHeight / 2, radius, circlePaint);
mRadius = radius * 2 - startY * 6;
canvas.translate(mWidth / 2 - mRadius / 2, mHeight / 2 - mRadius / 2);
if (ringModes.size() == 0)
return;
//画圆环
drawCycle(canvas);
drawSquare(canvas);
}
//画圆环
private void drawCycle(Canvas canvas) {
float sweepPercent = 0f;
CircleRingMode mode;
startPercent = initStartPercent;
for (int i = 0; i < ringModes.size(); i++) {
mode = ringModes.get(i);
cyclePaint.setColor(mode.getColorValue());
startPercent += (sweepPercent - 0.5f);
if (i < 2) {
sweepPercent = (mode.getProgress() + 0.5f) * 360 / 100f;
startPercent -= 1f;
} else if (i == ringModes.size() - 1) {
sweepPercent = 360f + initStartPercent - startPercent - 0.5f;
} else {
sweepPercent = mode.getProgress() * 360 / 100f;
}
canvas.drawArc(new RectF(0, 0, mRadius, mRadius), startPercent, sweepPercent, false, cyclePaint);
}
}
private void drawSquare(Canvas canvas) {
int base = Math.min(mWidth, mHeight) / 25;
int startTop = mHeight / 2 - base * 3;
int startLeft = mWidth / 2 + base;
for (CircleRingMode mode : ringModes) {
linePaint.setColor(mode.getColorValue());
canvas.drawRect(new Rect(startLeft, startTop, startLeft + base, startTop + base), linePaint);
canvas.drawText(mode.getProgress() + "%", startLeft + base + 10, startTop + base, linePaint);
startTop += base * 2;
}
}
/**
* 获取宽和高
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight = getDefaultSize(getSuggestedMinimumWidth(), heightMeasureSpec);
radius = Math.min(mWidth / 2, mHeight / 2) - UnitUtil.dp2px(mContext, 24);
Log.d(TAG, "onMeasure: mWidth: " + mWidth + ",mHeight: " + mHeight);
}
public void setData(List<CircleRingMode> modeList) {
this.setData(modeList,0);
}
public void setData(List<CircleRingMode> modeList, float hour) {
if (modeList.size() == 0)
return;
if (this.ringModes.size() > 0)
this.ringModes.clear();
this.ringModes.addAll(modeList);
this.startPercent = this.initStartPercent = 360 * hour / 24f - 90;
invalidate();
}
}
Github项目地址
有不对的地方欢迎留言指正,不胜感激.