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,表示程度