这是在学习android的Canvas绘图技巧时做的一个实例。主要用的核心方法就是canvas.save,canvas.rotate,

canvas.translate以及canvas.restore。通过这个小例子的练习,可以更好的掌握这些方法的使用。

先贴一张最终的效果图吧,如下:

来一步一步的来写代码吧。新建一个项目,然后新建类MyView继承自View,下面我们来首先将外盘画出来。即最外面的那个

圆。代码如下:

 package com.example.testcanvas;

 import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.DragEvent;
import android.view.View;
/**
* 画一个仪表盘出来,哈哈
* @author fuly1314
*
*/
public class MyView extends View{ private int width;//view宽度
private int height;//view的高度
private int radius;//外层圆的半径 public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
} public MyView(Context context) {
super(context);
} protected void onDraw(Canvas canvas) { width = getWidth();
height = getHeight();
radius = width/2;//外部圆盘的半径 Paint paintCircle = new Paint();
paintCircle.setStyle(Paint.Style.STROKE);
paintCircle.setStrokeWidth(5);
paintCircle.setAntiAlias(true);
//画出外层的圆盘
canvas.drawCircle(width/2, height/2, radius, paintCircle); } }

代码很简单,相信这一步大家都不陌生。我们将圆形置在了屏幕的中心位置,并让半径为宽度的一半。其他的就不多说了。

接下来我们来画刻度值。

首先刻度值有两种,一种是大的刻度值,这类刻度值都是可以被6整除的,另外一类则不可以。这个在画的时候很容易解决。

不容易解决的是要按照一定的弧度来把刻度值给画上。如果在这个时候,不利用canvcas.rotate方法的话,简直是要愁死人了。

还好有这么一个方法可以很方便的解决这个问题。我们先看代码,然后再来详细解释。增加的代码如下:

package com.example.testcanvas;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.DragEvent;
import android.view.View;
/**
* 画一个仪表盘出来,哈哈
* @author fuly1314
*
*/
public class MyView extends View{ private int width;//view宽度
private int height;//view的高度
private int radius;//外层圆的半径
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
} public MyView(Context context) {
super(context);
} protected void onDraw(Canvas canvas) { width = getWidth();
height = getHeight();
radius = width/2;//外部圆盘的半径 Paint paintCircle = new Paint();
paintCircle.setStyle(Paint.Style.STROKE);
paintCircle.setStrokeWidth(5);
paintCircle.setAntiAlias(true);
//画出外层的圆盘
canvas.drawCircle(width/2, height/2, radius, paintCircle); /**
* 下面的代码要画出刻度值
*/ for(int i =0;i<24;i++)
{ Paint paintDegree = new Paint(); if(i%6 == 0)//画的是大的刻度值
{ paintDegree.setStrokeWidth(5);
paintDegree.setTextSize(30); canvas.drawLine(width/2, height/2-radius, width/2,
height/2-radius+60, paintDegree);
canvas.drawText(String.valueOf(i), width/2-paintDegree.measureText(String.valueOf(i))/2,
height/2-radius+90, paintDegree);
}else//画的是小刻度
{
paintDegree.setStrokeWidth(3);
paintDegree.setTextSize(25); canvas.drawLine(width/2, height/2-radius, width/2,
height/2-radius+30, paintDegree);
canvas.drawText(String.valueOf(i), width/2-paintDegree.measureText(String.valueOf(i))/2,
height/2-radius+60, paintDegree); } //将坐标系绕点(width/2,height/2)旋转15度
canvas.rotate(360/24, width/2, height/2); } } }

红色部分就是增加的画刻度线的代码。代码最核心的地方就是上面被黄色背景标注的地方。我们知道在画刻度的时候,刻度0是最好画的,如果

每一个刻度都能像画0刻度这么容易的话,岂不是太过瘾了!Android可谓在此时深深的了解你的愿望啊,于是Canvas.rotate方法就过来拯救你了!

你把一个圆分成了24份,每一份是15度,那么从画0刻度开始每次画一个刻度就把坐标系旋转15度,再来画下一个刻度,是不是就一直跟画0刻度的

方法是一样的了呢?显然是的!之所以应用rotate方法让坐标系围绕圆心旋转15度,可不就是为了这个嘛!因此你会发现在循环画刻度时,都是按照

画刻度0的画法来画的!!怎么样,神奇吧!至此,所有的刻度我们算是画好了。

最后我们来画两根指针。

再次修改代码如下:

 package com.example.testcanvas;

 import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.DragEvent;
import android.view.View;
/**
* 画一个仪表盘出来,哈哈
* @author fuly1314
*
*/
public class MyView extends View{ private int width;//view宽度
private int height;//view的高度
private int radius;//外层圆的半径
private int hcount = 0;
20 private int mcount = 0; public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
} public MyView(Context context) {
super(context);
} protected void onDraw(Canvas canvas) { width = getWidth();
height = getHeight();
radius = width/2;//外部圆盘的半径 Paint paintCircle = new Paint();
paintCircle.setStyle(Paint.Style.STROKE);
paintCircle.setStrokeWidth(5);
paintCircle.setAntiAlias(true);
//画出外层的圆盘
canvas.drawCircle(width/2, height/2, radius, paintCircle); /**
* 下面的代码要画出刻度值
*/ for(int i =0;i<24;i++)
{ Paint paintDegree = new Paint(); if(i%6 == 0)//画的是大的刻度值
{ paintDegree.setStrokeWidth(5);
paintDegree.setTextSize(30); canvas.drawLine(width/2, height/2-radius, width/2,
height/2-radius+60, paintDegree);
canvas.drawText(String.valueOf(i), width/2-paintDegree.measureText(String.valueOf(i))/2,
height/2-radius+90, paintDegree);
}else//画的是小刻度
{
paintDegree.setStrokeWidth(3);
paintDegree.setTextSize(25); canvas.drawLine(width/2, height/2-radius, width/2,
height/2-radius+30, paintDegree);
canvas.drawText(String.valueOf(i), width/2-paintDegree.measureText(String.valueOf(i))/2,
height/2-radius+60, paintDegree); } //将坐标系绕点(width/2,height/2)旋转15度
canvas.rotate(360/24, width/2, height/2); } canvas.save();//先保存下,因为下面要用到坐标的平移
86
87 //将坐标系的平移至原点为(wdith/2,height/2)的地方
88 canvas.translate(width/2, height/2);
89
90 int hourRadius = radius*2/4;
91 int minuteRaidus = radius*3/4;
92 int hx = (int) (hourRadius*Math.cos(hcount));
93 int hy = (int) (hourRadius*Math.sin(hcount));
94 int mx = (int) (minuteRaidus*Math.cos(mcount));
95 int my = (int) (minuteRaidus*Math.sin(mcount));
96
97 Paint paintHour = new Paint();
98 paintHour.setStrokeWidth(7);
99
100 canvas.drawLine(0, 0,hx , hy, paintHour);
101
102 Paint paintMinute = new Paint();
103 paintMinute.setStrokeWidth(3);
104
105 canvas.drawLine(0, 0, mx, my, paintMinute);
106
107 canvas.restore();
108
109
110 mcount++;
111
112 if(mcount%10 == 0){
113 hcount++;
114 }
115
116 postInvalidateDelayed(500); } }

核心代码就是黄色背景标注的代码!因为在画指针的时候,我们发现还是不爽,还有从屏幕左上角来计算坐标。所以就使用canvas.translate方法

直接将坐标系给平移了。直接平移到圆心,因为我们的出发点就在圆形。接下来是不是画那些指针就十分容易了!在这里,我们使用了两个变量来控制

指针的转动分别是hcount和mcount。在转动的过程中怎么确定指针的坐标呢?画个图来说明吧。如下:

代码中的求指针的坐标的时候就是按照这个思路来求的。相信上面的代码应该没有什么问题了吧。当然了,代码写的乱,有很多可以优化的时候。

这里只是为了练习下canvas的方法,不去深究了。最后别忘记调用postInvalidateDelayed方法来进行刷新。

至此,这个能动的仪表盘就做好了。下面把它放进布局中吧。修改activity_main.xml代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
> <com.example.testcanvas.MyView
android:layout_width="match_parent"
android:layout_height="match_parent"
/> </RelativeLayout>

直接运行程序吧!效果跟上面的贴图一样。

android之旋转的刻度盘的更多相关文章

  1. Android立体旋转动画实现与封装(支持以X、Y、Z三个轴为轴心旋转)

    本文主要介绍Android立体旋转动画,或者3D旋转,下图是我自己实现的一个界面 立体旋转分为以下三种: 1. 以X轴为轴心旋转 2. 以Y轴为轴心旋转 3. 以Z轴为轴心旋转--这种等价于andro ...

  2. Android 屏幕旋转 处理 AsyncTask 和 ProgressDialog 的最佳方案

    的最佳方案 标签: Android屏幕旋转AsyncTaskProgressDialog 2014-07-19 09:25 39227人阅读 评论(46) 收藏 举报 分类: [android 进阶之 ...

  3. android 屏幕旋转

    转自:http://blog.csdn.net/oyzhizhong/article/details/8131799 屏是LANDSCAPE的,要让它默认显示为PORTRAIT. 1.kernel里要 ...

  4. android手机旋转屏幕时让GridView的列数与列宽度自适应

    无意中打开了一年前做过的一个android应用的代码,看到里面实现的一个小功能点(如题),现写篇文章做个笔记.当时面临的问题是,在旋转屏幕的时候需要让gridview的列数与宽度能自适应屏幕宽度,每个 ...

  5. 【Android】[转] Android屏幕旋转使用OrientationEventListener的监听

    说明 遇到一个奇葩的问题,我在使用onConfigChanged拦截屏幕的横竖屏旋转时,发现直接进行180度的横屏/竖屏转换居然没有反应!查找原因发现仅对landscape或者portrait状态有用 ...

  6. Android中轴旋转特效实现,制作别样的图片浏览器

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/10766017 Android API Demos中有很多非常Nice的例子,这些例 ...

  7. Android图片旋转,缩放,位移,倾斜,对称完整示例(一)——imageView.setImageMatrix(matrix)和Matrix

    MainActivity如下: import android.os.Bundle; import android.view.MotionEvent; import android.view.View; ...

  8. Android开发 旋转屏幕导致Activity重建解决方法(转)

     文章来源:http://www.jb51.net/article/31833.htm Android开发文档上专门有一小节解释这个问题.简单来说,Activity是负责与用户交互的最主要机制,任何“ ...

  9. Android屏幕旋转

    一个手机最基本的旋转方向有上面4种,而在Android开发中,涉及到屏幕旋转的地方很多,而且各个函数给出的角度值都不一样,比如 Activity的getRotate,Camera的setDisplay ...

随机推荐

  1. Java对象的复制

      Java中对象的赋值分为浅拷贝和深拷贝 1.对象浅拷贝 public class CloneTest{ static class Emp{ String name; int age; Date h ...

  2. 关于开发Windows服务程序容易搞混的地方!

    在开发Windows服务程序时,我们一般需要添加安装程序,即:serviceInstaller,里面有几个关于名称属性,你都搞明白了吗? 1.Description:表示服务说明(描述服务是干什么的) ...

  3. [Bootstrap]7天深入Bootstrap(2)整体架构

    大多数Bootstrap的使用者都认为Bootstrap只提供了CSS组件 和JavaScript插件,其实CSS组件和JavaScript插件只是Bootstrap框架的表现形式而已,它们都是构建在 ...

  4. 【原创】记一次Sql2008R2的数据库订阅发布遇到的问题!

    1.首先新建一个空的数据库 CreditTest,里面没有任何表结构,视图,数据等. 2.在已连接的服务器的下方找到“复制”选项,然后兴建发布: ...(新建发布成功) ...(新建订阅成功) 3.问 ...

  5. Hibernate框架之入门

    1.Hibernate框架简述 Hibernate的核心组件在基于MVC设计模式的JAVA WEB应用中,Hibernate可以作为模型层/数据访问层.它通过配置文件(hibernate.proper ...

  6. 【iOS】Quartz2D简单介绍

    一.什么是Quartz2D Quartz 2D是⼀个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图 ...

  7. 搭建angularjs API文档站点

    提供一个国内可以访问的 angularjs API文档站点 http://i.frllk.com/ 文档直接在 github 上下载的: https://github.com/angular-cn/n ...

  8. bootstrap 弹出框点击其他区域时弹出框不消失选项设置

    默认情况下,bootstrap 弹出框点击其他区域时,弹出框会自动关闭,在很多时候,我们可能会希望达到和原生弹出框一样的效果,避免不小心点击其他区域时弹框自动隐藏,尤其是对于一些复杂的表单,重复填写可 ...

  9. 轻量级SaaS在线作图工具ProcessOn

    俗话说“一图胜千言”,在办公应用领域,流程图是一个非常好的表现企业业务流程或工作岗位规范等内容的展现形式,比如去给客户做调研,回来后都要描述出客户的关键业务流程,谁.什么时候.在什么地方.负责什么事情 ...

  10. 关于js中两种定时器的设置及清除

    1.JS中的定时器有两种: window.setTimeout([function],[interval]) 设置一个定时器,并且设定了一个等待的时间[interval],当到达时间后,执行对应的方法 ...