自定义汽车仪表盘
效果图:
![这里写图片描述](https://img-blog.csdn.net/20170619165156627)
获取控件的宽高
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
mCenterX = mWidth / 2f;
mCenterY = mHeight / 2f;
mRadius = (mHeight - offset * 2) / 2;
}
初始化画笔:
//最外层大圆弧的画笔
outerArcPaint = new Paint()
outerArcPaint.setStyle(Paint.Style.STROKE)
outerArcPaint.setStrokeWidth(mStrokeWidth)
outerArcPaint.setColor(Color.parseColor("#5555aa"))
outerArcPaint.setAntiAlias(true)
//最外层小圆弧的画笔
outerSmallArcPaint = new Paint()
outerSmallArcPaint.setAntiAlias(true)
outerSmallArcPaint.setStyle(Paint.Style.STROKE)
outerSmallArcPaint.setStrokeCap(Paint.Cap.ROUND)
outerSmallArcPaint.setStrokeWidth(dp2px(3))
SweepGradient sweepGradient = new SweepGradient(mCenterX, mCenterY, mColors, null)
outerSmallArcPaint.setShader(sweepGradient)
//内部圆的画笔
insideCirclePaint = new Paint()
insideCirclePaint.setColor(Color.parseColor("#27408B"))
insideCirclePaint.setStyle(Paint.Style.FILL)
insideCirclePaint.setAntiAlias(true)
//绘制速度值的画笔
speedPaint = new Paint()
speedPaint.setColor(Color.parseColor("#ff0000"))
speedPaint.setAntiAlias(true)
speedPaint.setStrokeWidth(4)
//刻度线的画笔
scaleLinePaint = new Paint()
scaleLinePaint.setStrokeWidth(4)
scaleLinePaint.setAntiAlias(true)
scaleLinePaint.setColor(Color.parseColor("#ECEFF1"))
//刻度数字的画笔
scaleTextPaint = new Paint()
scaleTextPaint.setTextSize(sp2px(16))
scaleTextPaint.setTypeface(Typeface.DEFAULT)
scaleTextPaint.setColor(Color.parseColor("#ECEFF1"))
scaleTextPaint.setAntiAlias(true)
mRectText = new Rect()
//绘制单位km/h的画笔
unitTextPaint = new Paint()
unitTextPaint.setColor(Color.parseColor("#ECEFF1"))
unitTextPaint.setAntiAlias(true)
unitTextPaint.setTypeface(Typeface.DEFAULT)
unitTextPaint.setTextSize(sp2px(16))
unitTextPaint.setTextAlign(Paint.Align.CENTER)
//指针的画笔
pointerPaint = new Paint()
pointerPaint.setStrokeCap(Paint.Cap.ROUND)
pointerPaint.setColor(Color.parseColor("#55aaaa"))
pointerPaint.setStrokeWidth(dp2px(3))
画圆弧
private void drawArc(Canvas canvas) {
RectF mRectFArc = new RectF((mWidth - mHeight) / 2 + offset, offset, mWidth - (mWidth - mHeight) / 2 - offset, mHeight - offset);
canvas.drawArc(mRectFArc, mStartAngle - 15, mSweepAngle + 30, false, outerArcPaint);
RectF mSmallRectFArc = new RectF((mWidth - mHeight) / 2 + offset + mLength1, offset + mLength1, mWidth - (mWidth - mHeight) / 2 - offset - mLength1, mHeight - offset - mLength1);
canvas.drawArc(mSmallRectFArc, mStartAngle - 15 + mSweepAngle + 30 - 360, 360 - (mSweepAngle + 30), false, outerSmallArcPaint);
canvas.drawCircle(mCenterX, mCenterY, mRadius / 2, insideCirclePaint);
}
绘制文本
private void drawText(Canvas canvas) {
int xOffset = dp2px(22);
if (mVelocity >= 100) {
drawDigitalTube(canvas, mVelocity / 100, -xOffset);
drawDigitalTube(canvas, (mVelocity - 100) / 10, 0);
drawDigitalTube(canvas, mVelocity % 100 % 10, xOffset);
} else if (mVelocity >= 10) {
drawDigitalTube(canvas, -1, -xOffset);
drawDigitalTube(canvas, mVelocity / 10, 0);
drawDigitalTube(canvas, mVelocity % 10, xOffset);
} else {
drawDigitalTube(canvas, -1, -xOffset);
drawDigitalTube(canvas, -1, 0);
drawDigitalTube(canvas, mVelocity, xOffset);
}
canvas.drawText(mHeaderText, mWidth / 2, mHeight / 2 + unitTextPaint.getTextSize() + offset, unitTextPaint);
}
画刻度
private void drawScale(Canvas canvas) {
double cos = Math.cos(Math.toRadians(mStartAngle - 180));
double sin = Math.sin(Math.toRadians(mStartAngle - 180));
int xOff = (mWidth - mHeight) / 2 + offset + mStrokeWidth / 2;
int yOff = offset - mStrokeWidth / 2;
float x0 = (float) (xOff + mRadius * (1 - cos));
float y0 = (float) (yOff + mRadius * (1 - sin));
float x1 = (float) (xOff + mRadius - (mRadius - mLength1) * cos);
float y1 = (float) (yOff + mRadius - (mRadius - mLength1) * sin);
canvas.save();
canvas.drawLine(x0, y0, x1, y1, scaleLinePaint);
float angle = mSweepAngle * 1f / mSection;
for (int i = 0; i < mSection; i++) {
canvas.rotate(angle, mCenterX, mCenterY);
canvas.drawLine(x0, y0, x1, y1, scaleLinePaint);
}
canvas.restore();
float α;
float[] p;
angle = mSweepAngle * 1f / mSection;
for (int i = 0; i <= mSection; i++) {
α = mStartAngle + angle * i;
p = getCoordinatePoint(mRadius - mLength2, α);
if (α % 360 > 135 && α % 360 < 225) {
scaleTextPaint.setTextAlign(Paint.Align.LEFT);
} else if ((α % 360 >= 0 && α % 360 < 45) || (α % 360 > 315 && α % 360 <= 360)) {
scaleTextPaint.setTextAlign(Paint.Align.RIGHT);
} else {
scaleTextPaint.setTextAlign(Paint.Align.CENTER);
}
scaleTextPaint.getTextBounds(mHeaderText, 0, mTexts[i].length(), mRectText);
int txtH = mRectText.height();
if (i <= 1 || i >= mSection - 1) {
canvas.drawText(mTexts[i], p[0], p[1] + txtH / 2, scaleTextPaint);
} else if (i == 3) {
canvas.drawText(mTexts[i], p[0] + txtH / 2, p[1] + txtH, scaleTextPaint);
} else if (i == mSection - 3) {
canvas.drawText(mTexts[i], p[0] - txtH / 2, p[1] + txtH, scaleTextPaint);
} else {
canvas.drawText(mTexts[i], p[0], p[1] + txtH, scaleTextPaint);
}
}
}
画指针
private void drawPointer(Canvas canvas) {
float θ = mStartAngle + mSweepAngle * (mVelocity - mMin) / (mMax - mMin);
float[] p1 = getCoordinatePoint(mRadius - mStrokeWidth, θ);
float[] p2 = getCoordinatePoint(mRadius / 10 * 6, θ);
canvas.drawLine(p1[0], p1[1], p2[0], p2[1], pointerPaint);
}
下载地址:
源码下载