Canvas作为绘图的直接对象提供了几个非常有用的方法。下面先介绍一下,然后再来练习。
1.Canvas.save(); 保存画布,大概功能就是将之前所有绘制的的图型保存起来。
2.Canvas.restore(); 这个方法是进行图像合并操作。将我们在save();之前的图像与之后的图像进行合并。
3.Canvas.translate(); Canvas.rotate(); 从字面上理解是画布的平移与翻转。在没有操作之前原点是(0,0),我们可以用translate(x,y) 进行平移,之后原点就是(x,y).同理rotate(degrees),是将坐标进行旋转。
下面看看这个表怎么画
先分析一下:它有一个圆,刻度,三个指针,还有数字,圆好画,直接绘制就行了
但是刻度,数值怎么绘制呢?难道要用三角函数一点一点的算,指针也用三角函数算?
当然这样算,肯定也是行的,但那样就太麻烦了。其实如果用我们前面介绍的方法,就可以简单的实现!
通过平移与旋转 就能解决不同角度的问题。
首先要画图,不能没有画笔,那就来创建个吧
//创建画笔 这里创建多个 是因为可以让下面代码看着简单点,其实也可以少创建的
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setStrokeWidth(2);
mCirclePaint.setColor(Color.parseColor("#303F9F"));
mCirclePaint.setStyle(Paint.Style.STROKE);
mLongLinePaint = new Paint();
mLongLinePaint.setColor(Color.parseColor("#7C8B87"));
mLongLinePaint.setStrokeWidth(4);
mLongLinePaint.setAntiAlias(true);
mSmallLinePaint = new Paint();
mSmallLinePaint.setColor(Color.parseColor("#7C8B87"));
mSmallLinePaint.setStrokeWidth(2);
mSmallLinePaint.setAntiAlias(true);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(Color.parseColor("#999999"));
mTextPaint.setTextSize(26);
mMinPaint = new Paint();
mMinPaint.setColor(Color.parseColor("#45BDA0"));
mMinPaint.setAntiAlias(true);
mMinPaint.setStrokeWidth(3);
mSecPaint = new Paint();
mSecPaint.setColor(Color.parseColor("#45BDA0"));
mSecPaint.setAntiAlias(true);
mSecPaint.setStrokeWidth(1);
mHoursPaint = new Paint();
mHoursPaint.setColor(Color.parseColor("#45BDA0"));
mHoursPaint.setAntiAlias(true);
mHoursPaint.setStrokeWidth(5);
画笔有了那么就可以来,绘图了。
先来画个圆,没什么可讲的,这里能用到 宽 和高,先得到
<span style="white-space:pre"> </span>width = getWidth();
height = getHeight();
canvas.drawCircle(width / 2, height / 2, width / 2 - mMargin, mCirclePaint);
再来画刻度线 ,当
刻度线,数值 画完了,保存一下画布
for (int i = 0; i < 12; i++) { // 绘制两个刻度线 通过旋转来控制
if (i == 0 | i == 3 | i == 6 | i == 9 | i == 12) {
canvas.drawLine(width / 2, height / 2 - (width / 2 - mMargin), width / 2, height / 2 - (width / 2 - mMargin) + 30, mLongLinePaint);
canvas.drawText(String.valueOf(i), width / 2 - 5, height / 2 - (width / 2 - mMargin) - 20, mTextPaint);
} else {
canvas.drawText(String.valueOf(i), width / 2 - 5, height / 2 - (width / 2 - mMargin) - 20, mTextPaint);
canvas.drawLine(width / 2, height / 2 - (width / 2 - mMargin), width / 2, height / 2 - (width / 2 - mMargin) + 10, mSmallLinePaint);
}
canvas.rotate(30, width / 2, height / 2); // 让画布旋转30度
}
canvas.save();
再绘制 三个指针,与合并绘图。注释比较详细
canvas.translate(width / 2, height / 2); // 将坐标原点移动到 中心
canvas.rotate(180); // 让角度从0刻度开始
canvas.rotate(mHoursAngle); // 把小时指针旋转到指定角度
canvas.drawLine(0, 0, 0, width / 2 - 3 * mMargin, mHoursPaint); // 绘制小时线段
canvas.rotate(360 - mHoursAngle); // 将旋转角度 旋转至 0 刻度位置(相当与初始化)
canvas.rotate(mMinAngle);
canvas.drawLine(0, 0, 0, width / 2 - 2 * mMargin, mMinPaint);
canvas.rotate(360 - mMinAngle);
canvas.rotate(mSecAngle);
canvas.drawLine(0, 0, 0, width / 2 - 2 * mMargin + 50, mSecPaint);
canvas.restore(); // 合并绘图
发个消息,让它实时更新时间
handler.sendEmptyMessageDelayed(1, 200); // 发个消息,绘制具体时间
最后把 Handler 实现就行了
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
Date date = new Date();
mHours = date.getHours();
mMim = date.getMinutes();
mSec = date.getSeconds();
mHoursAngle = mHours * 30; // 在从0刻度时,算起的角度
mMinAngle = mMim * 6; // 在从0刻度时,算起的角度
mSecAngle = mSec * 6; // 在从0刻度时,算起的角度
Log.d("-----", "mHoursAngle" + mHoursAngle + " mMinAngle: " + mMinAngle + " mSecAngle : " + mSecAngle);
invalidate(); // 绘制图像
return false;
}
});
OK,这样基本就行了,大概就是用上面CanVas的几个方法,来绘制需要角度的图像。
最后说明 如果没有save(); 调用restore();会报错的。