Android类似汽车仪表器

项目中要使用仪表器的功能,来提醒一些东西,自己也就实现了一个。

这个是单纯draw出来的,没有加入什么图片,画的太潦草了。

自己也有一些疑问,会先提出来,希望知道可以回答解惑。

话不多说,我也不客气了,我先做个残忍的对比,就是想做出的效果和自己做的效果做个对比。

这是要的效果图,感觉很不错,这是在站酷找的设计图

 

但是自己做出来的就差远了,后来想想也许思路错了,我纠结我当时怎么想的啊,我竟然全是用画出来,我傻啊

用动画效果多好啊,用贴图多好啊。上图吧

 

这一对比我就不忍目睹啊。。。。。。

但这也是教训,也放上来吧。

public class RingEstimateView extends LinearLayout {
	private final Context mContext;
	private int centerX;// 中心x轴
	private int centerY;// 中心y轴
	private int ringWidth;// 颜色环的大小
	private int radius;// 颜色环的半径
	private int spaceOutsideRadian;// 颜色环与外环的距离
	private int spaceInsideRadian;// 颜色环与内环的距离
	private Canvas mCanvas;// 画布
	private mTask task;// 异步重画
	// 计算每个环块的弧度
	private float ringRadian = 3;
	// 环块绘制开始的角度
	private final float startRadian = 136.5f;
	// 环块绘制结束的角度
	private final float endRadian = 360 + 45;
	private static ExecutorService FULL_TASK_EXECUTOR;// 线程池

	static {
		FULL_TASK_EXECUTOR = (ExecutorService) Executors.newCachedThreadPool();// 单线程的线程池
	};

	public RingEstimateView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.mContext = context;
		this.setWillNotDraw(false);

	}

	@Override
	public void draw(Canvas canvas) {
		this.mCanvas = canvas;

		ringWidth = dip2px(mContext, 20);// 设置圆环的宽度
		radius = dip2px(mContext, getWidth() / 8);// 设置半径

		spaceOutsideRadian = dip2px(mContext, 15);// 环与外环的间隙
		spaceInsideRadian = dip2px(mContext, radius / 2 - 15);// 环与内环的间隙

		centerX = getWidth() / 2;
		centerY = getHeight() / 2;

		drwaAngleRingForNumber();// 画成多少块
		drawOutAndInCircle();// 画出外边的圆

		if (task == null) {
			task = new mTask("", 0);
			task.executeOnExecutor(FULL_TASK_EXECUTOR, 0);
		}

		task.drawRemind();
		super.draw(canvas);
	}

	/**
	 * 根据要画成多少块,画
	 */
	private void drwaAngleRingForNumber() {
		// 初始化画笔
		Paint paint = createPaint(
				mContext.getResources().getColor(R.color.green), ringWidth);
		paint.setAntiAlias(true);
		// 绘制弧度的圆环
		multipleColor mc = new multipleColor();// 生成多种颜色
		float start = startRadian;
		// 绘制圆环的范围
		RectF oval = createRectF(centerY - radius, radius * 2
				+ (centerY - radius), centerX - radius, radius * 2
				+ (centerX - radius));
		for (; start < (endRadian); start += ringRadian * 2) {// 循环角度,画出环块
			paint.setColor(mc.getWhiteColor());// 设置不同的颜色
			mCanvas.drawArc(oval, start, ringRadian, false, paint);
		}
	}

	/**
	 * 画出内、外边的圆
	 */
	private void drawOutAndInCircle() {
		int mRadius = radius + spaceOutsideRadian + ringWidth;
		RectF mOval = createRectF(centerY - mRadius, mRadius * 2
				+ (centerY - mRadius), centerX - mRadius, mRadius * 2
				+ (centerX - mRadius));
		Paint mPaint = createPaint(
				mContext.getResources().getColor(R.color.floralwhite), 4);
		int startRadian = 140;
		mPaint.setAlpha(150);
		mCanvas.drawArc(mOval, startRadian, 260, false, mPaint);// 画出弧圆

		// 画出两天横线
		float sinX = (float) Math.sin(50 * Math.PI / 180) * mRadius;
		float cosY = (float) Math.cos(50 * Math.PI / 180) * mRadius;
		mCanvas.drawLine(centerX - sinX, centerY + cosY - 1,
				(centerX - sinX) - 20, centerY + cosY, mPaint);
		mCanvas.drawLine(centerX + sinX, centerY + cosY - 1,
				(centerX + sinX) + 20, centerY + cosY, mPaint);

		// 画出文字low max
		mPaint.setTextSize(19);
		mPaint.setStrokeWidth(2);
		mCanvas.drawText("LOW", centerX - sinX - 63, centerY + cosY + 5, mPaint);
		mCanvas.drawText("MAX", centerX + sinX + 25, centerY + cosY + 5, mPaint);
		// 绘制里面的圆
		int contentRadius = radius - spaceInsideRadian;
		Paint tPaint = createPaint(
				mContext.getResources().getColor(R.color.ghostwhite), 5);
		tPaint.setStyle(Paint.Style.FILL);
		mCanvas.drawCircle(centerX, centerY, contentRadius, tPaint);
	}

	/**
	 * 画出提醒的内容
	 */
	public void drawRemindContent(String remindContent, int remindLevel) {
		task = new mTask(remindContent, remindLevel);
		task.executeOnExecutor(FULL_TASK_EXECUTOR, 0);
	}

	class mTask extends AsyncTask<Integer, Integer, Void> {
		private String remindContent;
		private int remindLevel;
		private final float pointStartRadian = startRadian + 1.5f;// 开始画的弧度
		private int pointDrawRadian = 0;// 要画的弧度
		private int bufRadian = 0;// 存一个过渡的弧度

		public mTask(String remindContent, int remindLevel) {
			this.remindContent = remindContent;
			this.remindLevel = remindLevel;
			pointDrawRadian = (int) ((remindLevel / 100.0f) * 44) * 6;
		}

		@Override
		protected Void doInBackground(Integer... params) {
			for (int i = 0; i < pointDrawRadian; i++) {
				bufRadian++;
				publishProgress(params);
				try {
					Thread.sleep(20);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			return null;
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			RingEstimateView.this.postInvalidate();
			super.onProgressUpdate(values);
		}

		/**
		 * 画出提醒
		 */
		public void drawRemind() {

			drawOutCircleToColor();// 画出彩色部分
			drawRemindContent();// 内容
			drawRemindPoint();
		}

		/**
		 * 画出外面圆的颜色
		 */
		private void drawOutCircleToColor() {
			float pointRadian = pointStartRadian + bufRadian;// 指针的角度
			// 初始化画笔
			Paint paint = createPaint(
					mContext.getResources().getColor(R.color.green), ringWidth);
			paint.setAntiAlias(true);
			// 绘制弧度的圆环
			multipleColor mc = new multipleColor();// 生成多种颜色
			float start = startRadian;
			// 绘制圆环的范围
			RectF oval = createRectF(centerY - radius, radius * 2
					+ (centerY - radius), centerX - radius, radius * 2
					+ (centerX - radius));
			for (; start < (pointRadian); start += ringRadian * 2) {// 循环角度,画出环块
				paint.setColor(mc.nextColor());// 设置不同的颜色
				mCanvas.drawArc(oval, start, ringRadian, false, paint);
			}

		}

		/**
		 * 添加指针视图
		 */
		private void addPointView() {
			int deviateRadian = 180 + 45;// 视图本来偏离的角度
			float pointRadian = pointStartRadian;// 指针的角度
			int pointX = radius - spaceInsideRadian;// 开始指针离原点的距离
			float cosPoint = (float) Math.cos(pointRadian * Math.PI / 180);
			float sinPoint = (float) Math.sin(pointRadian * Math.PI / 180);
			float pointStartX = (centerX + cosPoint * pointX);
			float pointStartY = (centerY + sinPoint * pointX);

			Bitmap bmp = BitmapFactory.decodeResource(mContext.getResources(),
					R.drawable.accel_pointer);
			// rotate(bmp,(int)(deviateRadian + pointRadian));
			mCanvas.drawBitmap(bmp, pointStartX, pointStartY, null);

			// 定义矩阵对象
			Matrix matrix = new Matrix();
			// 缩放原图
			matrix.postScale(1f, 1f);
			// 向左旋转45度,参数为正则向右旋转
			// matrix.postRotate((int) (deviateRadian));
			matrix.setSinCos(sinPoint, cosPoint);
			Bitmap dstbmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(),
					bmp.getHeight(), matrix, true);
			// 在画布上绘制旋转后的baby位图
			mCanvas.drawBitmap(dstbmp, pointStartX, pointStartY, null);

			int layoutX = px2dip(mContext,
					pointStartX - sinPoint * bmp.getWidth());
			int layoutY = px2dip(mContext, pointStartY);
			mCanvas.drawBitmap(rotate(bmp, (int) (deviateRadian)), pointStartX,
					pointStartY, null);
		}

		/**
		 * 位图旋转方法
		 * 
		 * @param b
		 * @param degrees
		 * @return
		 */
		public Bitmap rotate(Bitmap b, int degrees) {
			if (degrees != 0 && b != null) {
				Matrix m = new Matrix();
				m.setRotate(degrees, (float) b.getWidth() / 2,
						(float) b.getHeight() / 2);
				try {
					Bitmap b2 = Bitmap.createBitmap(b, 0, 0, b.getWidth(),
							b.getHeight(), m, true);
					if (b != b2) {
						b.recycle(); // Bitmap操作完应该显示的释放
						b = b2;
					}
				} catch (OutOfMemoryError ex) {

				}
			}
			return b;
		}

		/**
		 * 画出提醒的指针
		 */
		private synchronized void drawRemindPoint() {
			if (remindLevel < 0) {
				remindLevel = 0;
			} else if (remindLevel > 100) {
				remindLevel = 100;
			}

			int pointLength = dip2px(mContext, spaceInsideRadian - ringWidth - 10);
			int pointX = radius - spaceInsideRadian;// 开始指针离原点的距离
			float pointRadian = pointStartRadian + bufRadian;// 指针的角度
			float cosPoint = (float) Math.cos(pointRadian * Math.PI / 180);
			float sinPoint = (float) Math.sin(pointRadian * Math.PI / 180);
			float pointStartX = (centerX + cosPoint * pointX);
			float pointStartY = (centerY + sinPoint * pointX);
			float pointStopX = (centerX + cosPoint * (pointX + pointLength));
			float pointStopY = (centerY + sinPoint * (pointX + pointLength));
			mCanvas.drawLine(
					pointStartX,
					pointStartY,
					pointStopX,
					pointStopY,
					createPaint(
							mContext.getResources()
									.getColor(R.color.ghostwhite), 5));
		}

		/**
		 * 画出提醒的内容
		 */
		private synchronized void drawRemindContent() {
			// Canvas mCanvas = new Canvas();
			// 画出中间的文字
			if (remindContent == null || "".equals(remindContent)) {
				return;
			}
			// 加上提醒内容
			multipleColor mc = new multipleColor();
			Paint tPaint = createPaint(mc.getRemindColor(remindLevel), 10);
			
			tPaint.setStyle(Paint.Style.FILL);
			tPaint.setTextSize(45);
			tPaint.setFakeBoldText(true);
			mCanvas.drawText(remindContent, centerX - 45, centerY + 45/3, tPaint);
		}
	}

	// 创建一个矩形
	private RectF createRectF(float top, float bottom, float left, float right) {
		RectF mOval = new RectF();
		mOval.top = top;
		mOval.bottom = bottom;
		mOval.left = left;
		mOval.right = right;
		return mOval;
	}

	private Paint createPaint(int paintColor, int strokeWidth) {
		Paint mPaint = new Paint();
		mPaint.setAntiAlias(true);// 消除锯齿
		mPaint.setStyle(Paint.Style.STROKE);// 绘制空心圆
		mPaint.setColor(paintColor);
		mPaint.setStrokeWidth(strokeWidth);
		return mPaint;
	}

	/**
	 * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
	 */
	public static int dip2px(Context context, float dpValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dpValue * scale + 0.5f);
	}

	/**
	 * 根据手机的分辨率从 px的单位 转成为 dp(像素)
	 */
	public static int px2dip(Context context, float dpValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dpValue / scale + 0.5f);
	}

	/*
	 * 生成多种颜色
	 */
	class multipleColor {
		private int currentIndex = 0;
		private List<Integer> colors;

		public multipleColor() {
			colors = new ArrayList<Integer>();
			for (int i = 0; i < 5; i++) {
				colors.add(Color.rgb(0, 255, 0));
			}
			for (int i = 0; i <= 255; i += 12) {
				int c = Color.rgb(i, 255, 0);
				colors.add(c);
			}
			for (int i = 255; i >= 0; i -= 16) {
				int c = Color.rgb(255, i, 0);
				colors.add(c);
			}
			for (int i = 0; i < 5; i++) {
				colors.add(Color.rgb(255, 0, 0));
			}
		}

		// 取得颜色
		public int nextColor() {
			if (currentIndex < colors.size()) {
				int color = colors.get(currentIndex);
				currentIndex++;
				return color;

			}
			return Color.rgb(255, 255, 255);
		}

		// 取得白颜色
		public int getWhiteColor() {
			return Color.rgb(255, 255, 255);
		}

		/**
		 * 取得提醒内容的颜色
		 * 
		 * @return
		 */
		public int getRemindColor(int remindLevel) {
			int colorNum = (remindLevel / 100) * 45;
			return colors.get(colorNum);
		}

	}

	/**
	 * 设置背景
	 * 
	 * @param color
	 */
	public void setBackground(int color) {
		this.setBackground(color);
	}

}

 视图函数就是这个了,我是懒了,注释都没写多少了。。

使用就是在activity 中加入:

<framework.ui.RingEstimateView
            android:id="@+id/bwv_test"
            android:layout_width="fill_parent"
            android:layout_height="400dp" >
        </framework.ui.RingEstimateView>

然后在class中:

tev = (RingEstimateView) findViewById(R.id.bwv_test);

tev.drawRemindContent("急速",100);//这个函数后面int参数可以使用0~100,表示程度

 

 

 

 
 

 

 

 

posted @ 2014-03-11 18:08  菜园的鸟  阅读(925)  评论(0编辑  收藏  举报