项目中要使用仪表器的功能,来提醒一些东西,自己也就实现了一个。
这个是单纯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,表示程度