一个仪表盘自定义控件
程序员文章站
2022-06-08 16:26:36
...
最近开发中设计给出了一个类似于仪表盘的控件,虽然可以用多张图代替,但是还是写了一个类似的自定义控件,成果如下图:
1、首先把原点设置在圆心
//把方框平移到正中间
canvas.translate(dx, dy);
canvas.save();
canvasR = Math.min(getWidth(), getHeight()) / 2;
markWidth = canvasR / 20;
tableWidth = canvasR / 10;
mPaint.setStyle(Paint.Style.STROKE);
2、从外围开始描绘控件
//填写文字刻度
mPaint.setTextSize(outTextSize);
int count = 0;
while (count < mMaxCount) {
//填写外围文字
Rect bounds = new Rect();
String text = 100 / (mMaxCount - 1) * count + "";
mPaint.getTextBounds(text, 0, text.length(), bounds);
float offSet = (bounds.bottom - bounds.top);
//角度
float angle = startAngle + sweepAngle / (mMaxCount - 1) * count;
textWidth = offSet + 3;//3间距显得好看点
//半径
float r = canvasR - textWidth;
canvas.rotate(90 + angle, getmX(r, angle), getmY(r, angle));
canvas.drawText(text, getmX(r, angle), getmY(r, angle), mPaint);
canvas.rotate(-90 - angle, getmX(r, angle), getmY(r, angle));
//填写大刻度
canvas.drawLine(getmX(r - 3, angle), getmY(r - 3, angle), getmX(r - markWidth, angle), getmY(r - markWidth, angle), mPaint);
int count0 = 1;
//填写小刻度
while (count > 0 && count0 < mMinCount) {
//角度
float angle0 = angle - sweepAngle / (mMaxCount - 1) + sweepAngle / (mMaxCount - 1) * count0 / mMinCount;
canvas.drawLine(getmX(r - markWidth / 2, angle0), getmY(r - markWidth / 2, angle0), getmX(r - markWidth, angle0), getmY(r - markWidth, angle0), mPaint);
count0++;
}
count++;
}
//刻度下面弧线
float markR = canvasR - textWidth - markWidth;
RectF markRectf = new RectF(-markR, -markR, markR, markR);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawArc(markRectf, startAngle, sweepAngle, false, mPaint);
float tableR = markR - canvasR / 40 - tableWidth / 2;
RectF mTableRectF = new RectF(-tableR, -tableR, tableR, tableR);
//进度条底部
Path tablePath = new Path();
tablePath.addArc(mTableRectF, startAngle - 90, sweepAngle);
//计算路径的长度
PathMeasure pathMeasure = new PathMeasure(tablePath, false);
float length = pathMeasure.getLength();
float step = length / 21;
DashPathEffect dashPathEffect = new DashPathEffect(new float[]{step * 9 / 10, step / 10}, 0);
mPaint.setPathEffect(dashPathEffect);
mPaint.setStrokeWidth(tableWidth);
canvas.rotate(90);
canvas.drawPath(tablePath, mPaint);
canvas.rotate(-90);
//进度条
Path progressPath = new Path();
progressPath.addArc(mTableRectF, startAngle - 90, sweepAngle * progress / 100);
SweepGradient mColorShader = new SweepGradient(0, 0, SWEEP_GRADIENT_COLORS, null);
mPaint.setShader(mColorShader);
canvas.rotate(90);
canvas.drawPath(progressPath, mPaint);
canvas.rotate(-90);
//画带阴影的圆
float circleR = tableR - canvasR / 40 - tableWidth / 2;
initPaint();
canvas.drawCircle(-canvasR / 160, canvasR / 160, circleR, mPaint);
mPaint.setColor(Color.WHITE);
canvas.drawCircle(0, 0, circleR, mPaint);
mPaint.setColor(Color.parseColor("#cccccc"));
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(0, 0, circleR, mPaint);
//画内圆
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.parseColor("#fafafa"));
canvas.drawCircle(0, 0, circleR * 2 / 5, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.parseColor("#dddddd"));
canvas.drawCircle(0, 0, circleR * 2 / 5, mPaint);
//画进度小圆点
mPaint.setColor(Color.parseColor("#FF6610"));
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(getmX(circleR - canvasR / 20, startAngle + sweepAngle * progress / 100)
, getmY(circleR - canvasR / 20, startAngle + sweepAngle * progress / 100), canvasR / 40, mPaint);
//画中间字符
Rect bounds = new Rect();
String text = progress + "%";
mPaint.setTextSize(proTextSize);
mPaint.getTextBounds(text, 0, text.length(), bounds);
float offSet = (bounds.bottom - bounds.top);
Rect bounds2 = new Rect();
String text2 = decText;
mPaint.setTextSize(decTextSize);
mPaint.setColor(Color.parseColor("#cccccc"));
mPaint.getTextBounds(text, 0, text.length(), bounds2);
float offSet2 = (bounds2.bottom - bounds2.top);
canvas.drawText(text2, 0, (offSet2 + offSet + 3) / 2, mPaint);
mPaint.setColor(Color.parseColor("#FF6610"));
mPaint.setTextSize(proTextSize);
canvas.drawText(text, 0, (offSet2 + offSet + 3) / 2 - offSet2 - 3, mPaint);
求x,y坐标方法
private float getmX(float r, float angle) {
return (float) Math.cos(angle * Math.PI / 180) * r;
}
private float getmY(float r, float angle) {
return (float) Math.sin(angle * Math.PI / 180) * r;
}
源码:https://download.csdn.net/download/qq_40667603/11945307