您的位置:首页 > 移动开发 > Android开发

自定义表盘(未彻底完成)

2016-12-01 17:41 120 查看
看到大家都在自定义view玩。我也来玩一下,其实自定义View,画图不难,难的是数据的计算。如果你要做一个可扩展的View,里面的数据肯定是要灵活可变的。

这个时候,你就不可以把数据写死。下面是我自定义的View。

首先要搞清楚Canvas绘图的角度计算。0刻度不是在上方。Canvas里面的画弧度的起始度数(0)是以钟表的三点钟为0刻度的。

所以,第一步是要画3/4的圆弧的表盘。

/**
* 绘制表盘
*
* @param canvas
*/
private void drawPlate(Canvas canvas, RectF oval) {
//开始画表盘,仪表盘不是一个完整的圆,是3/4的圆,所以起始度数是134度,结束点是44(404)度。
for (int i = 134; i < 405; i += (270 / scales.length)) {
canvas.drawArc(oval, i, 2, false, paint);
//最后一个连结弧不要
if (i + 270 / scales.length < 405) {
canvas.drawArc(oval, i + 4, 270 / scales.length - 6, false, paint);
}
}
}

其中指针是一个只有2°的弧。其中数组scales为仪表盘的刻度数值,可以自定义。

绘制了表盘之后,开始绘制表盘指针读数,比如汽车读数为50的时候,应该是怎么样的。

/**
* 绘制读数
*
* @param canvas
*/
private void drawRegistration(Canvas canvas, RectF oval) {
// 用来更改值,判断是否是动画
int prog = isStartCartoom ? cartoomProgress : polluteNum;
/*开始画读数颜色*/
int index_pro = getProIndex(prog);//当前所处的段位,比如100,在默认数据中属于第二段。101属于第三段
int start_degrees = 138;//开始画颜色的起始度数
float rotation = 0f;//指针偏转角度
Log.e("info", "prog=" + prog);
Log.e("info", "index_pro=" + index_pro);
for (int i = 0; i < index_pro; i++) {
int d_value = i == 0 ? scales[0] : scales[i] - scales[i - 1];
num_paint.setColor(colors[i % colors.length]);// 设置圆环的颜色
int end1 = prog < scales[i] ? i == 0 ? prog : prog - scales[i - 1] : d_value;
end1 = end1 * (270 / scales.length - 6) / d_value;// 算出来画的角度
canvas.drawArc(oval, start_degrees, end1, false, num_paint);
rotation = start_degrees + 90 + end1;
start_degrees += 45;
}
if (contains(prog)) {
rotation = 225 + (270 / scales.length) * (index_pro - 1);
Log.e("info", "rotation=" + rotation);
}
//指针
drawPointer(canvas, rotation);
}

/**
* 绘制指针
*
* @param canvas
* @param rotation
*/
private void drawPointer(Canvas canvas, float rotation) {
// 用来更改值,判断是否是动画
int prog = isStartCartoom ? cartoomProgress : polluteNum;
//圆心X的坐标
int centre = getWidth() / 2;
int radius = (int) (centre - roundWidth / 2); // 圆环的半径
float scaleX = defaultWidth / width;
float scaleY = defaultHeight / height;
//表盘指针
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.chart_index);
/* 控制旋转 */
Matrix matrix = new Matrix();
/**
* 开始画指针
*/
float sx = (float) ((getWidth() / bitmap.getWidth()) * 0.8);
matrix.setScale(sx, sx);
matrix.setRotate(rotation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
canvas.drawBitmap(bitmap, (radius - bitmap.getWidth() / 2) + 10 * scaleX, radius - bitmap.getHeight() / 2 + 10 * scaleY,
new Paint());
bitmap.recycle();
float text_size = text_paint.measureText(String.valueOf(prog));
text_paint.setColor(colors[getProIndex(prog) % colors.length]);
canvas.drawText(String.valueOf(prog), radius - text_size / 2, centre + bitmap.getHeight() / 2 + 30, text_paint);
 }

当前最不可少的当然需要一个动画了。没有动画怎么都感觉不好看。
通过Timer来实现的动画,你也可以通过轻量级的异步线程AsyncTask来实现

class CartoomEngine {
public Handler mHandler;
public boolean mBCartoom; // 是否正在作动画
public Timer mTimer; // 用于作动画的TIMER
public MyTimerTask mTimerTask; // 动画任务
public int mTimerInterval; // 定时器触发间隔时间(ms)
public float mCurFloatProcess; // 作动画时当前进度值

@SuppressLint("HandlerLeak")
public CartoomEngine() {
mHandler = new Handler() {

@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
switch (msg.what) {
case TIMER_ID: {
if (mBCartoom == false) {
return;
}
mCurFloatProcess += 1;
setCartoomProgress((int) mCurFloatProcess);
if (mCurFloatProcess >= polluteNum) {
stopCartoom();
}
}
break;
}
}

};

mBCartoom = false;
mTimer = new Timer();
mTimerInterval = 5;
mCurFloatProcess = 0;

}

public synchronized void startCartoom(int time) {
if (time <= 0 || mBCartoom == true) {
return;
}
mBCartoom = true;
isStartCartoom = true;
setCartoomProgress(0);
mCurFloatProcess = 0;
mTimerTask = new MyTimerTask();
mTimer.schedule(mTimerTask, 0, mTimerInterval);

}

public synchronized void stopCartoom() {

if (mBCartoom == false) {
return;
}
mBCartoom = false;
setNum(polluteNum);
isStartCartoom = false;
if (mTimerTask != null) {
mTimerTask.cancel();
mTimerTask = null;
}
}

private final static int TIMER_ID = 0x0010;

class MyTimerTask extends TimerTask {

@Override
public void run() {
Message msg = mHandler.obtainMessage(TIMER_ID);
msg.sendToTarget();
}

}
}完整的代码链接在代码片里 https://code.csdn.net/snippets/2022443
指针图片在附件里

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android