Android仿汽车速度仪表盘

共 10702字,需浏览 22分钟

 ·

2021-07-02 09:06

效果图:



问题


  • 如何线性颜色变化?

  Shader mShader = new LinearGradient(pointX - raduis, pointY, pointX + raduis, pointY,                new int[]{0xFF445EED, 0xFF072AE9, 0xFF0625CE}, null, Shader.TileMode.CLAMP);


完整的自定义View

public class SpeedControlView extends View implements Runnable {    //画笔    private Paint mPaint, textPaint, speedAreaPaint;    private Context mContext;    //屏幕宽高    private int screenWidth, screenHeight;    //仪表盘圆的半径    private float raduis, sRaduis;    //圆心    private int pointX, pointY;    //文字的偏移量    private float textScale;    //速度指针变化的位置    private float linePointerX, linePointerY;    //速度    private int speed;    //速度范围的2个扇形外切矩形    private RectF speedRectF, speedRectFInner;    //速度控制模式  1 加速  2 减速  3 手刹    private int type;
// 速度文字 绘制的XY坐标 private int baseX, baseY;
//屏幕密度 private float mDensityDpi;
//设置速度控制模式 public void setType(int type) { this.type = type; }
//开始重绘 private boolean start = true;
public void setStart(boolean start) { this.start = start; }
// 设置速度 并重绘视图 public void setSpeed(int speed) { this.speed = speed; if (speed > 0) { postInvalidate(); } }

public SpeedControlView(Context context) { this(context, null); }
public SpeedControlView(Context context, AttributeSet attrs) { this(context, attrs, 0); }
public SpeedControlView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context;
//获取屏幕宽高// screenWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth();// screenHeight = ((Activity) context).getWindowManager().getDefaultDisplay().getHeight();
//获取屏幕宽高 和 屏幕密度dpi DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); screenWidth = displayMetrics.widthPixels; screenHeight = displayMetrics.heightPixels; mDensityDpi = displayMetrics.densityDpi / 320; //320为我的测试机dpi密度,以次绘制视图 //关闭硬件加速 setLayerType(LAYER_TYPE_SOFTWARE, null); //设置抗锯齿 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setAntiAlias(true); //设置画笔样式 mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(5 * mDensityDpi);
//初始化 圆心左边 和 半径 raduis = screenWidth / 3; pointX = pointY = screenWidth / 2;// pointY = screenHeight / 4;
//设置抗锯齿 textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); textPaint.setAntiAlias(true); //设置画笔颜色 textPaint.setColor(Color.WHITE); // 获取字体并设置画笔字体 Typeface typeface = Typeface.createFromAsset(mContext.getAssets(), "kt.ttf"); textPaint.setTypeface(typeface); //设置抗锯齿 speedAreaPaint = new Paint(Paint.ANTI_ALIAS_FLAG); speedAreaPaint.setAntiAlias(true); //设置画笔样式 speedAreaPaint.setStyle(Paint.Style.FILL); // 设置速度范围扇形的渐变颜色 Shader mShader = new LinearGradient(pointX - raduis, pointY, pointX + raduis, pointY, new int[]{0xFF445EED, 0xFF072AE9, 0xFF0625CE}, null, Shader.TileMode.CLAMP); speedAreaPaint.setShader(mShader); // 初始化速度范围的2个扇形外切矩形 speedRectF = new RectF(pointX - raduis + 10 * mDensityDpi, pointY - raduis + 10 * mDensityDpi, pointX + raduis - 10 * mDensityDpi, pointY + raduis - 10 * mDensityDpi); speedRectFInner = new RectF(pointX - raduis / 2, pointY - raduis / 2, pointX + raduis / 2, pointY + raduis / 2); }
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.YELLOW);
//绘制外层圆,两个外圈,两个内圈 drawCicle(canvas);
//绘制速度范围扇形区域 speedAreaPaint.setColor(0x7E3F51B5); drawSpeedArea(canvas);
//变换画笔颜色 绘制刻度 mPaint.setColor(0xBF3F6AB5); drawScale(canvas);
//变换画笔颜色 绘制速度标识文字 textPaint.setTextSize(25 * mDensityDpi); mPaint.setColor(Color.WHITE); sRaduis = raduis - 50 * mDensityDpi; textScale = Math.abs(textPaint.descent() + textPaint.ascent()) / 2; Log.e("textScale", textScale + "");
drawText(canvas);
//绘制中间文字内容 drawCenter(canvas); }
/** * 绘制外层圆 */ private void drawCicle(Canvas canvas) { mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(0xFF343434); canvas.drawCircle(pointX, pointY, raduis, mPaint);
//外圈2个圆 mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(0xBF3F6AB5); mPaint.setStrokeWidth(4 * mDensityDpi); canvas.drawCircle(pointX, pointY, raduis, mPaint); mPaint.setStrokeWidth(3 * mDensityDpi); canvas.drawCircle(pointX, pointY, raduis - 10 * mDensityDpi, mPaint);
//内圈2个圆 mPaint.setStrokeWidth(5 * mDensityDpi); mPaint.setColor(0xE73F51B5); canvas.drawCircle(pointX, pointY, raduis / 2, mPaint); mPaint.setColor(0x7E3F51B5); canvas.drawCircle(pointX, pointY, raduis / 2 + 5 * mDensityDpi, mPaint); mPaint.setStrokeWidth(3 * mDensityDpi);
}
/** * 绘制速度区域扇形 */ private void drawSpeedArea(Canvas canvas) { int degree; if (speed < 210) { degree = speed * 36 / 30; } else { degree = 210 * 36 / 30; }
canvas.drawArc(speedRectF, 144, degree, true, speedAreaPaint);
// TODO: 2016/5/12 //不显示中间的内圈的扇形区域 mPaint.setColor(0xFF343434); mPaint.setStyle(Paint.Style.FILL); canvas.drawArc(speedRectFInner, 144, degree, true, mPaint); mPaint.setStyle(Paint.Style.STROKE); }

/** * 绘制刻度 */ private void drawScale(Canvas canvas) { for (int i = 0; i < 60; i++) { if (i % 6 == 0) { canvas.drawLine(pointX - raduis + 10 * mDensityDpi, pointY, pointX - raduis + 50 * mDensityDpi, pointY, mPaint); } else { canvas.drawLine(pointX - raduis + 10 * mDensityDpi, pointY, pointX - raduis + 30 * mDensityDpi, pointY, mPaint); } canvas.rotate(6, pointX, pointY); } }
/** * 绘制速度标识文字 */ private void drawText(Canvas canvas) {// canvas.save();// canvas.rotate(-36, pointX, pointY); for (int i = 0; i < 8; i++) { int value = 30 * i; String TEXT = String.valueOf(value); switch (value) { case 0: // 计算Baseline绘制的起点X轴坐标 baseX = (int) (pointX - sRaduis * Math.cos(Math.PI / 5) + textPaint.measureText(TEXT) / 2 + textScale / 2); // 计算Baseline绘制的Y坐标 baseY = (int) (pointY + sRaduis * Math.sin(Math.PI / 5) + textScale / 2); break; case 30: baseX = (int) (pointX - raduis + 50 * mDensityDpi + textPaint.measureText(TEXT) / 2); baseY = (int) (pointY + textScale); break; case 60: baseX = (int) (pointX - sRaduis * Math.cos(Math.PI / 5) + textScale); baseY = (int) (pointY - sRaduis * Math.sin(Math.PI / 5) + textScale * 2); break; case 90: baseX = (int) (pointX - sRaduis * Math.cos(2 * Math.PI / 5) - textScale / 2); baseY = (int) (pointY - sRaduis * Math.sin(2 * Math.PI / 5) + 2 * textScale); break; case 120: baseX = (int) (pointX + sRaduis * Math.sin(Math.PI / 10) - textPaint.measureText(TEXT) / 2); baseY = (int) (pointY - sRaduis * Math.cos(Math.PI / 10) + 2 * textScale); break; case 150: baseX = (int) (pointX + sRaduis * Math.cos(Math.PI / 5) - textPaint.measureText(TEXT) - textScale / 2); baseY = (int) (pointY - sRaduis * Math.sin(Math.PI / 5) + textScale * 2); break; case 180: baseX = (int) (pointX + sRaduis - textPaint.measureText(TEXT) - textScale / 2); baseY = (int) (pointY + textScale); break; case 210: baseX = (int) (pointX + sRaduis * Math.cos(Math.PI / 5) - textPaint.measureText(TEXT) - textScale / 2); baseY = (int) (pointY + sRaduis * Math.sin(Math.PI / 5) - textScale / 2); break; }// baseX = (int) (pointX - raduis + 50 * mDensityDpi + textPaint.measureText(TEXT) / 2);// baseY = (int) (pointY + textScale); canvas.drawText(TEXT, baseX, baseY, textPaint);// canvas.rotate(36, pointX, pointY); }// canvas.restore(); }
/** * 绘制中间文字内容 */ private void drawCenter(Canvas canvas) { //速度 textPaint.setTextSize(60 * mDensityDpi); float tw = textPaint.measureText(String.valueOf(speed)); baseX = (int) (pointX - tw / 2); baseY = (int) (pointY + Math.abs(textPaint.descent() + textPaint.ascent()) / 4); canvas.drawText(String.valueOf(speed), baseX, baseY, textPaint);
//单位 textPaint.setTextSize(20 * mDensityDpi); tw = textPaint.measureText("km/h"); baseX = (int) (pointX - tw / 2); baseY = (int) (pointY + raduis / 4 + Math.abs(textPaint.descent() + textPaint.ascent()) / 4); canvas.drawText("km/h", baseX, baseY, textPaint); }

@Override public void run() { int speedChange; while (start) { switch (type) { case 1://油门 speedChange = 3; break; case 2://刹车 speedChange = -5; break; case 3://手刹 speed = 0; default: speedChange = -1; break; } speed += speedChange; if (speed < 1) { speed = 0; } try { Thread.sleep(50); setSpeed(speed); } catch (InterruptedException e) { e.printStackTrace(); break; } } }}


调用:

@Overrideprotected void onResume() {    super.onResume();    if (speedControlView != null) {        speedControlView.setSpeed(0);        speedControlView.setStart(true);    }    new Thread(speedControlView).start();}
@Overrideprotected void onStop() { super.onStop(); if (speedControlView != null) { speedControlView.setSpeed(0); speedControlView.setStart(false); }}


具体的实现过程看代码,到这里就结束啦。

浏览 113
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报