自定义View之canvas绘制时钟
2015-11-11 09:54
288 查看
前边有2篇自定义的文章,主要是讲解如何自定义view,主要是讲如何对现有控件进行拓展,如何重写view,但是这2篇文章里面都很少有讲到如何通过canvas来绘制,今天主要介绍下Canvas。
先看一下绘制的demo。
下面先介绍下Canvas。
Canvas作为绘制图形的直接对象,提供了一下几个非常有用的方法:
1、Canvas.save();
2、Canvas.restore();
3、Canvas.translate();
4、Canvas.rotate();
5、canvas绘制点、线、图形、文字
Canvas.save()这个方法,从字面上可以理解为保存画布。他的作用就是将之前的所有已绘制的图像保存起来,让后续的操作就好像在一个新的图层上操作。
Canvas.restore()这个方法,则可以理解为Photoshop中的合并图层操作。他的作用是将我们在save()之后绘制的所有图像与save()之前的图像进行合并。
Canvas.translate()方法,应该理解为坐标系的平移,在调用translate(x,y)之后,则将原点(0,0)移动到了(x,y),之后的所有操作都将以(x,y)为原点执行。
Canvas.rotate()方法和translate一样,也是将坐标系旋转了一定的角度。rotate(15,x,y)意思就是以x,y为原点旋转15°
接下来分析下要怎么画这个图形。
1、仪表盘(大圆盘)
2、刻度线
3、刻度值
4、指针
第一步,仪表盘绘制。
第二步,刻度线。画刻度线的思路是这样的,每当画好一根线,就旋转响应的角度(15°),通过旋转画布——实际上是旋转了画图的坐标系,这就避免了进行复杂的三角函数运算,不需要通过三角函数运算算出每个点的坐标。第三步画刻度值的原理和其类似。看代码:
第四步,画指针。先用translate()方法将坐标原点从(0,0)移动到圆心(mWidth / 2,mHeight / 2),再画2条线就OK了。代码如下:
总的代码如下:
先看一下绘制的demo。
下面先介绍下Canvas。
Canvas作为绘制图形的直接对象,提供了一下几个非常有用的方法:
1、Canvas.save();
2、Canvas.restore();
3、Canvas.translate();
4、Canvas.rotate();
5、canvas绘制点、线、图形、文字
Canvas.save()这个方法,从字面上可以理解为保存画布。他的作用就是将之前的所有已绘制的图像保存起来,让后续的操作就好像在一个新的图层上操作。
Canvas.restore()这个方法,则可以理解为Photoshop中的合并图层操作。他的作用是将我们在save()之后绘制的所有图像与save()之前的图像进行合并。
Canvas.translate()方法,应该理解为坐标系的平移,在调用translate(x,y)之后,则将原点(0,0)移动到了(x,y),之后的所有操作都将以(x,y)为原点执行。
Canvas.rotate()方法和translate一样,也是将坐标系旋转了一定的角度。rotate(15,x,y)意思就是以x,y为原点旋转15°
接下来分析下要怎么画这个图形。
1、仪表盘(大圆盘)
2、刻度线
3、刻度值
4、指针
第一步,仪表盘绘制。
//画外圆 Paint paintCircle = new Paint(); paintCircle.setStyle(Paint.Style.STROKE); paintCircle.setAntiAlias(true); paintCircle.setStrokeWidth(5); canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, paintCircle);
第二步,刻度线。画刻度线的思路是这样的,每当画好一根线,就旋转响应的角度(15°),通过旋转画布——实际上是旋转了画图的坐标系,这就避免了进行复杂的三角函数运算,不需要通过三角函数运算算出每个点的坐标。第三步画刻度值的原理和其类似。看代码:
// 画刻度 Paint painDegree = new Paint(); paintCircle.setStrokeWidth(3); for (int i = 0; i < 24; i++) { // 区分整点与非整点 if (i == 0 || i == 6 || i == 12 || i == 18) { painDegree.setStrokeWidth(5); painDegree.setTextSize(30); canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2, mWidth / 2, mHeight / 2 - mWidth / 2 + 60, painDegree); // 画刻度 String degree = String.valueOf(i); canvas.drawText(degree, mWidth / 2 - painDegree.measureText(degree) / 2, mHeight / 2 - mWidth / 2 + 90, painDegree); } else { painDegree.setStrokeWidth(3); painDegree.setTextSize(15); canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2, mWidth / 2, mHeight / 2 - mWidth / 2 + 30, painDegree); // 画刻度 String degree = String.valueOf(i); canvas.drawText(degree, mWidth / 2 - painDegree.measureText(degree) / 2, mHeight / 2 - mWidth / 2 + 60, painDegree); } // 通过旋转画布简化坐标运算 canvas.rotate(15, mWidth / 2, mHeight / 2);
第四步,画指针。先用translate()方法将坐标原点从(0,0)移动到圆心(mWidth / 2,mHeight / 2),再画2条线就OK了。代码如下:
// 画圆心 Paint paintPointer = new Paint(); paintPointer.setStrokeWidth(30); canvas.drawPoint(mWidth / 2, mHeight / 2, paintPointer); // 画指针 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();
总的代码如下:
import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; /** * User: Picasso(380643397@qq.com) * Date: 2015-11-11 * Time: 09:23 * FIXME */ public class Clock extends View { private int mHeight, mWidth; public Clock(Context context) { super(context); } public Clock(Context context, AttributeSet attrs) { super(context, attrs); } public Clock(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { // 获取宽高参数 mWidth = getMeasuredWidth(); mHeight = getMeasuredHeight(); // 画外圆 Paint paintCircle = new Paint(); paintCircle.setStyle(Paint.Style.STROKE); paintCircle.setAntiAlias(true); paintCircle.setStrokeWidth(5); canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, paintCircle); // 画刻度 Paint painDegree = new Paint(); paintCircle.setStrokeWidth(3); for (int i = 0; i < 24; i++) { // 区分整点与非整点 if (i == 0 || i == 6 || i == 12 || i == 18) { painDegree.setStrokeWidth(5); painDegree.setTextSize(30); canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2, mWidth / 2, mHeight / 2 - mWidth / 2 + 60, painDegree); //画刻度 String degree = String.valueOf(i); canvas.drawText(degree, mWidth / 2 - painDegree.measureText(degree) / 2, mHeight / 2 - mWidth / 2 + 90, painDegree); } else { painDegree.setStrokeWidth(3); painDegree.setTextSize(15); canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2, mWidth / 2, mHeight / 2 - mWidth / 2 + 30, painDegree); String degree = String.valueOf(i); //画刻度 canvas.drawText(degree, mWidth / 2 - painDegree.measureText(degree) / 2, mHeight / 2 - mWidth / 2 + 60, painDegree); } // 通过旋转画布简化坐标运算 canvas.rotate(15, mWidth / 2, mHeight / 2); } // 画圆心 Paint paintPointer = new Paint(); paintPointer.setStrokeWidth(30); canvas.drawPoint(mWidth / 2, mHeight / 2, paintPointer); // 画指针 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(); } }
相关文章推荐
- 汉诺塔
- Zookeeper-Zookeeper可以干什么
- 80端口被系统占用
- C#中Config文件中,特殊符号的书写方法。
- Android中ListView分页加载数据
- 【Oracle】Oracle 12c DB In-Memory入门实验手册(二)
- Zookeeper--Zookeeper是什么
- 系统启动过程和系统安装过程
- UOJ #148. 【NOIP2015】跳石头 二分
- Linux命令:nohup、df、du与/dev/null
- jdk8之jstat命令使用说明
- hadoop2.2伪分布式安装
- 2002年,程序员和 Unix 大神们的桌面长啥样?
- java 动态代理学习(Proxy,InvocationHandler)
- 关于SharePoint 的Client object model该何时load和execut query的一点自己的看法
- LibSVM使用指南
- 打开Genesis设置单位为mm
- HDU 1281——棋盘游戏——————【最大匹配、枚举删点、邻接表方式】
- 射频识别技术漫谈(21)——RC系列射频芯片的天线设计
- java web 过滤器的执行先后顺序