Android仿汽车速度仪表盘
效果图:

问题
如何线性颜色变化?
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();//获取屏幕宽高 和 屏幕密度dpiDisplayMetrics 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);}@Overrideprotected 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);}@Overridepublic 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;}}}}
调用:
protected void onResume() {super.onResume();if (speedControlView != null) {speedControlView.setSpeed(0);speedControlView.setStart(true);}new Thread(speedControlView).start();}protected void onStop() {super.onStop();if (speedControlView != null) {speedControlView.setSpeed(0);speedControlView.setStart(false);}}
具体的实现过程看代码,到这里就结束啦。
评论
