public class CarSpeedDashboardSurfaceView extends SurfaceView implements SurfaceHolder.Callback.Runnable {
SurfaceHolder surfaceHolder;
private boolean isDrawing;
private Paint mPaintOutDashboard;// External code table arc brush
private Paint mPaintSpeedPoint;// The pen for the pointer to the code table
private Paint mPaintSpeedScale;// add a pencil to the table
private Paint mPaintSpeedScaleText;// write text on the scale
private Paint mPaintSpeedText;// Real-time codetable corresponds to numeric brush
private int outDashBoardWidth = 40;// The width of the arc of the external codetable
private float rotateValue = 50;// Animation needs to change the arc Angle
private float DEFAULT_START_ANGLE = 50;// The default rotation Angle is (360-260)/2 when the canvas is moved to the center
public CarSpeedDashboardSurfaceView(Context context) {
this(context, null);
}
public CarSpeedDashboardSurfaceView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CarSpeedDashboardSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
setKeepScreenOn(true);
// setBackgroundColor(Color.TRANSPARENT);
// setZOrderOnTop(true);
// surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
init();
}
/** * Initialization parameters */
private void init(a) {
mPaintOutDashboard = new Paint();
mPaintOutDashboard.setStrokeWidth(outDashBoardWidth);
mPaintOutDashboard.setStyle(Paint.Style.STROKE);
mPaintOutDashboard.setTextAlign(Paint.Align.CENTER);
mPaintOutDashboard.setAntiAlias(true);
mPaintOutDashboard.setStrokeCap(Paint.Cap.ROUND);
mPaintSpeedPoint = new Paint();
mPaintSpeedPoint.setColor(Color.BLACK);
mPaintSpeedPoint.setStrokeWidth(20);
mPaintSpeedPoint.setAntiAlias(true);
mPaintSpeedPoint.setStyle(Paint.Style.STROKE);
mPaintSpeedPoint.setTextAlign(Paint.Align.CENTER);
mPaintSpeedPoint.setStrokeCap(Paint.Cap.ROUND);
mPaintSpeedScale = new Paint();
mPaintSpeedScale.setColor(Color.BLUE);
mPaintSpeedScale.setStrokeWidth(5);
mPaintSpeedScale.setAntiAlias(true);
mPaintSpeedScale.setStyle(Paint.Style.STROKE);
mPaintSpeedScaleText = new Paint();
mPaintSpeedScaleText.setColor(Color.BLACK);
mPaintSpeedScaleText.setStrokeWidth(3);
mPaintSpeedScaleText.setTextSize(26);
;
mPaintSpeedScaleText.setAntiAlias(true);
mPaintSpeedText = new Paint();
mPaintSpeedText.setColor(Color.BLACK);
mPaintSpeedText.setTextSize(48);
;
mPaintSpeedText.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
mPaintSpeedText.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = measureSpec(widthMeasureSpec);
int height = measureSpec(heightMeasureSpec);
setMeasuredDimension(Math.min(width,height), Math.min(width,height));
// The gradient of width and height information can be obtained after the measurement is completed
LinearGradient sweepGradient = new LinearGradient(0
, getMeasuredHeight(), getMeasuredWidth()
, getMeasuredHeight()
, Color.BLUE, Color.RED, Shader.TileMode.CLAMP);
mPaintOutDashboard.setShader(sweepGradient);
}
private int measureSpec(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
int defaultWidth = 400;
switch (specMode) {
case MeasureSpec.EXACTLY:
defaultWidth = specSize;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
defaultWidth = 400;
break;
}
return defaultWidth;
}
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
isDrawing = true;
new Thread(this).start();
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {}@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
isDrawing = false;
}
@Override
public void run(a) {
while (isDrawing) {
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if(canvas! =null) { canvas.drawColor(Color.WHITE); drawDashBoard(canvas); }}finally {
if(canvas ! =null) { surfaceHolder.unlockCanvasAndPost(canvas); }}}}private void drawDashBoard(Canvas canvas) {
// Draw the outer ring
canvas.drawArc(outDashBoardWidth / 2, outDashBoardWidth / 2, Math.min(getMeasuredWidth(), getMeasuredHeight()) - outDashBoardWidth / 2, Math.min(getMeasuredWidth(), getMeasuredHeight()) - outDashBoardWidth / 2.140.260.false, mPaintOutDashboard);
drawSpeedScale(canvas);
// Draw the progress display in the progress bar
canvas.drawArc(outDashBoardWidth / 2, outDashBoardWidth / 2, Math.min(getMeasuredWidth(), getMeasuredHeight()) - outDashBoardWidth / 2, Math.min(getMeasuredWidth(), getMeasuredHeight()) - outDashBoardWidth / 2.140, rotateValue - DEFAULT_START_ANGLE, false, mPaintSpeedPoint);
drawSpeedPoint(canvas);
drawCenterSpeedSize(canvas);
}
/** * draws the scale and its corresponding code value **@param canvas
*/
private void drawSpeedScale(Canvas canvas) {
canvas.save();
float sweepAngle = 260;
float a = sweepAngle / 26;
canvas.translate(Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2, Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2);
canvas.rotate(DEFAULT_START_ANGLE);
for (int i = 0; i <= 26; i++) {
if (i == 0 || i == 26 || i % 5= =0) {
canvas.drawLine(0, Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2 - outDashBoardWidth, 0, Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2 - 80, mPaintSpeedScale);
} else {
canvas.drawLine(0, Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2 - outDashBoardWidth, 0, Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2 - 60, mPaintSpeedScale);
}
String text = i * 10 + "";
Rect rect = new Rect();
String msg = "999";
mPaintSpeedScaleText.getTextBounds(msg, 0, msg.length(), rect);
// canvas.drawText(text, 0, text.length(),0, Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2 - 85, mPaintSpeedScaleText);
// canvas.rotate(a);
canvas.rotate(-90);
canvas.translate(-1 * (Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2 - outDashBoardWidth - 60-rect.width()/2), 0);
canvas.rotate(90 - DEFAULT_START_ANGLE - a * i);
canvas.drawText(text, 0, text.length(), 0.0, mPaintSpeedScaleText);
canvas.rotate(-1 * (90 - DEFAULT_START_ANGLE - a * i));
canvas.translate(Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2 - outDashBoardWidth - 60-rect.width()/2.0);
canvas.rotate(90);
canvas.rotate(a);
//
}
canvas.restore();
}
/** * draws a pointer to the codetable **@param canvas
*/
private void drawSpeedPoint(Canvas canvas) {
canvas.drawPoint(Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2, Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2, mPaintSpeedPoint);
canvas.save();
canvas.translate(Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2, Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2);
canvas.rotate(rotateValue);
canvas.drawLine(0, Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2 - outDashBoardWidth * 4.0.0, mPaintSpeedPoint);
canvas.restore();
}
/** * draws the corresponding codetable value **@param canvas
*/
private void drawCenterSpeedSize(Canvas canvas) {
String value = Math.round(rotateValue - 50) + "";
Rect rect = new Rect();
mPaintSpeedText.getTextBounds(value, 0, value.length(), rect);
canvas.drawText(value, 0, value.length(), Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2 - rect.width() / 2
, Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2 - 40, mPaintSpeedText);
}
// Dynamic change
public void setValue(float value){
this.rotateValue=310-value; }}Copy the code