这个系列主要是介绍下Android自定义View和Android绘图机制,自己能力有限,如果在介绍过程中有什么错误,欢迎指正
在上一篇Android绘图系列(二)——自定义View绘制基本图形中我们可以绘制一些基本的图形了,这篇我们就来综合画一个仪表盘
在绘制这个仪表盘之前我们得先说下.Canvas的操作
相关操作 | 简要介绍 |
---|---|
save | 保存当前画布状态 |
restore | 回滚到上一次保存的状态 |
translate | 相对于当前位置位移 |
rotate | 旋转 |
首先,我们来看一下前面两个方法
在讲解这两个方法之前,首先来了解一下Android绘图的坐标体系,这个其实这个前面已经讲了,这里不赘述,而Canvas.save()这个方法,从字面上的意思可以理解为保存画布,他的作用就是讲之前的图像保存起来,让后续的操作能像在新的画布一样操作,这跟PS的图层基本差不多
而Canvas.restore()这个方法,则可以理解为合并图层,,就是将之前保存下来的东西合并
而后面两个方法,从字母上理解画布平移或者旋转,但是把他理解为坐标旋转更加形象,前面说了,我们绘制的时候默认坐标点事左上角的起始点,那么我们调用translate(x,y)之后,则将原点(0,0)移动到(x,y)之后的所有绘图都是在这一点上执行的,这里可能说的不够详细,相信我们绘制完今天的例子就会有一个理解的
这里我们取圆心为屏幕宽度一半,屏幕高度一半,半径是屏幕宽度一半
**
* Created by HFS on 2017/2/5.
* 仪表盘
*/
public class CircularView extends View {
// 宽高
private int mWidth;
private int mHeight;
// 构造方法
public CircularView(Context context, AttributeSet attrs) {
super(context, attrs);
// 获取屏幕的宽高
WindowManager wm = (WindowManager) getContext().getSystemService(
Context.WINDOW_SERVICE);
mWidth = wm.getDefaultDisplay().getWidth();
mHeight = wm.getDefaultDisplay().getHeight();
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
// 画外圆
Paint paintCircle = new Paint();
paintCircle.setAntiAlias(true);
paintCircle.setStyle(Paint.Style.STROKE);
paintCircle.setStrokeWidth(5);
canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, paintCircle);
}
}
效果
下面,我们来画刻度尺,这个也很简单,一条线而已,只要确定两个端点的位置就可以,第一根线还是比较容易确定的,那后面的我们怎么去确定尼?那些斜着的我们可以用三角函数去实现计算,但是这其实就是一个很简单的画图,三角函数的运算也要这么多,我们不经要思考,该怎么去简化他呢?其实Google已经为我们想好了
我们觉得这个不好画,主要是这个角度,那么如果我们将画布以中心为原点旋转到需要的角度尼?每当画好一根线,我们就旋转多少级角度,但是下一次划线的时候依然是第一次的坐标,但是实际上我们把画布重新还原到旋转钱的坐标了,所有的刻度线就已经画好了,通过旋转画布——实际上是旋转了画图的坐标轴,这就避免了万恶的三角函数了,通过这样一种相对论式的变换,间接简化了绘图,这时再去绘制这些刻度,是不是要简单了,只需要区别整点和非整点的刻度了
// 画刻度
Paint paintDegree = new Paint();
paintDegree.setStrokeWidth(3);
for (int i = 0; i < 24; i++) {
// 区别整点和非整点
if (i == 0 || i == 6 || i == 12 || i == 18) {
paintDegree.setStrokeWidth(5);
paintDegree.setTextSize(30);
canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,
mWidth / 2, mHeight / 2 - mWidth / 2 + 60, paintDegree);
String degree = String.valueOf(i);
canvas.drawText(degree,
mWidth / 2 - paintDegree.measureText(degree) / 2,
mHeight / 2 - mWidth / 2 + 90, paintDegree);
} else {
paintDegree.setStrokeWidth(3);
paintDegree.setTextSize(15);
canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,
mWidth / 2, mHeight / 2 - mWidth / 2 + 30, paintDegree);
String degree = String.valueOf(i);
canvas.drawText(degree,
mWidth / 2 - paintDegree.measureText(degree) / 2,
mHeight / 2 - mWidth / 2 + 60, paintDegree);
}
// 通过旋转画布简化坐标运算
canvas.rotate(15, mWidth / 2, mHeight / 2);
}
效果
就是两条直线
// 画指针
Paint paintHour = new Paint();
paintHour.setStrokeWidth(20);
Paint paintMinute = new Paint();
paintMinute.setStrokeWidth(10);
canvas.save();
canvas.translate(mWidth / 2, mHeight / 2);
canvas.drawLine(0, 0, 100, 100, paintHour);
canvas.drawLine(0, 0, 100, 200, paintMinute);
canvas.restore();
OK,这样一个仪表盘就绘制完了
Github地址