android之旋转的刻度盘

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

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

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

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

圆。代码如下:

  1 package com.example.testcanvas;
  2
  3 import android.content.Context;
  4 import android.graphics.Canvas;
  5 import android.graphics.Paint;
  6 import android.util.AttributeSet;
  7 import android.view.DragEvent;
  8 import android.view.View;
  9 /**
 10  * 画一个仪表盘出来,哈哈
 11  * @author fuly1314
 12  *
 13  */
 14 public class MyView extends View{
 15
 16     private int width;//view宽度
 17     private int height;//view的高度
 18     private int radius;//外层圆的半径

 22     public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
 23         super(context, attrs, defStyleAttr);
 24     }
 25
 26     public MyView(Context context, AttributeSet attrs) {
 27         super(context, attrs);
 28     }
 29
 30     public MyView(Context context) {
 31         super(context);
 32     }
 33
 34
 35     protected void onDraw(Canvas canvas) {
 36
 37         width = getWidth();
 38         height = getHeight();
 39         radius = width/2;//外部圆盘的半径
 40
 41         Paint paintCircle = new Paint();
 42         paintCircle.setStyle(Paint.Style.STROKE);
 43         paintCircle.setStrokeWidth(5);
 44         paintCircle.setAntiAlias(true);
 45         //画出外层的圆盘
 46         canvas.drawCircle(width/2, height/2, radius, paintCircle);

118     }
119
120 }

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

接下来我们来画刻度值。

首先刻度值有两种,一种是大的刻度值,这类刻度值都是可以被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的画法来画的!!怎么样,神奇吧!至此,所有的刻度我们算是画好了。

最后我们来画两根指针。

再次修改代码如下:

  1 package com.example.testcanvas;
  2
  3 import android.content.Context;
  4 import android.graphics.Canvas;
  5 import android.graphics.Paint;
  6 import android.util.AttributeSet;
  7 import android.view.DragEvent;
  8 import android.view.View;
  9 /**
 10  * 画一个仪表盘出来,哈哈
 11  * @author fuly1314
 12  *
 13  */
 14 public class MyView extends View{
 15
 16     private int width;//view宽度
 17     private int height;//view的高度
 18     private int radius;//外层圆的半径
 19     private int hcount = 0;
 20     private int mcount = 0;
 21
 22     public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
 23         super(context, attrs, defStyleAttr);
 24     }
 25
 26     public MyView(Context context, AttributeSet attrs) {
 27         super(context, attrs);
 28     }
 29
 30     public MyView(Context context) {
 31         super(context);
 32     }
 33
 34
 35     protected void onDraw(Canvas canvas) {
 36
 37         width = getWidth();
 38         height = getHeight();
 39         radius = width/2;//外部圆盘的半径
 40
 41         Paint paintCircle = new Paint();
 42         paintCircle.setStyle(Paint.Style.STROKE);
 43         paintCircle.setStrokeWidth(5);
 44         paintCircle.setAntiAlias(true);
 45         //画出外层的圆盘
 46         canvas.drawCircle(width/2, height/2, radius, paintCircle);
 47
 48         /**
 49          * 下面的代码要画出刻度值
 50          */
 51
 52         for(int i =0;i<24;i++)
 53         {
 54
 55             Paint paintDegree = new Paint();
 56
 57             if(i%6 == 0)//画的是大的刻度值
 58             {
 59
 60                 paintDegree.setStrokeWidth(5);
 61                 paintDegree.setTextSize(30);
 62
 63                 canvas.drawLine(width/2, height/2-radius, width/2,
 64                         height/2-radius+60, paintDegree);
 65                 canvas.drawText(String.valueOf(i), width/2-paintDegree.measureText(String.valueOf(i))/2,
 66                         height/2-radius+90, paintDegree);
 67             }else//画的是小刻度
 68             {
 69                 paintDegree.setStrokeWidth(3);
 70                 paintDegree.setTextSize(25);
 71
 72                 canvas.drawLine(width/2, height/2-radius, width/2,
 73                         height/2-radius+30, paintDegree);
 74                 canvas.drawText(String.valueOf(i), width/2-paintDegree.measureText(String.valueOf(i))/2,
 75                         height/2-radius+60, paintDegree);
 76
 77             }
 78
 79             //将坐标系绕点(width/2,height/2)旋转15度
 80             canvas.rotate(360/24, width/2, height/2);
 81
 82         }
 83
 84
 85         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);
117
118     }
119
120 }

核心代码就是黄色背景标注的代码!因为在画指针的时候,我们发现还是不爽,还有从屏幕左上角来计算坐标。所以就使用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>

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

时间: 2024-10-13 08:37:10

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

android圆形旋转菜单,并支持移动换位功能

LZ最近接手公司一个项目,需要写一个圆形的旋转菜单,并且支持菜单之间的移动换位,本来以为这种demo应该网上是很多的,想不到度娘也是帮不了我,空有旋转功能但是却不能换位置,所以LZ就只能靠自己摸索了. 最终LZ参考了网上的部分代码,重写了一个自定义的view终于实现了这个看似很吊,却没有实际意义的功能.在此贡献出来给广大码农们共享. 话不多说,先上代码: 自定义view类: public class RoundSpinView extends View { private Paint mPain

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

本文主要介绍Android立体旋转动画,或者3D旋转,下图是我自己实现的一个界面 立体旋转分为以下三种: 1. 以X轴为轴心旋转 2. 以Y轴为轴心旋转 3. 以Z轴为轴心旋转--这种等价于android默认自带的旋转动画RotateAnimation 实现立体旋转核心步骤: 1. 继承系统Animation重写applyTransformation方法 通过applyTransformation方法的回调参数 float interpolatedTime, Transformation t 来

Android图片旋转,缩放,位移,倾斜,对称完整示例(二)——Bitmap.createBitmap()和Matrix

MainActivity如下: package cc.c; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.widget.ImageView; /** * Demo描述: * 利用B

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

MainActivity如下: import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.ImageView; import android.app.Activity; import android.graphics.Matrix; /** * Demo描述:

android 屏幕旋转

转自:http://blog.csdn.net/oyzhizhong/article/details/8131799 屏是LANDSCAPE的,要让它默认显示为PORTRAIT. 1.kernel里要旋转FrameBuffer.  启动参数里加入fbcon=rotate:1    (0:正常屏; 1:顺时钟转90度; 2:转180度; 3:顺时钟转270度;)最后生成的autoconf.h里有类似项:#define CONFIG_CMDLINE "console=ttySAC0,115200 f

Android 屏幕旋转适配全解析

原创文章,转载请注明 ( 来自:http://blog.csdn.net/leejizhou/article/details/51233342 李济洲的博客 ) 这篇博文给大家介绍下,当手机屏幕旋转时我们应当怎么去处理,首先了解下默认情况下Android进行屏幕旋转的原理,当手机进行旋转时重力感应sensor起到作用,会将Activity销毁并按照横屏的屏幕尺寸进行重新构造,生命周期如下图所示,一句话总结就是默认情况下Activity进行屏幕旋转会自动进行onDestroy并重新onCreate

Android 屏幕旋转生命周期以及处理方法

工作期间项目需要经常旋转屏幕,还有平板.所以会经常考虑Android 屏幕旋转生命周期,所以也有相应的处理方法.主要有两种办法解决.是根据屏幕旋转的生命周期具体使用.屏幕旋转时候,如果不做任何处理,activity会经过销毁到重建的过程.这种效果都不是想要的. 一.方法一 是在配置文件的activity加上这个 android:configChanges="keyboardHidden|orientation|screenSize"  这句话意思就是配置双引号里面参数意义,软键盘隐藏,

android 屏幕旋转 不重新加载oncreate

当手机设定了使用横屏或者竖屏的时候,还想要使用重力感应,可以设置activity属性 android:screenOrientation="sensor" 但是每次翻转屏幕,都会重新调用oncreate,要想不重新加载程序的话,需要使用如下设置android:configChanges="orientation|keyboardHidden|screenSize" android 屏幕旋转 不重新加载oncreate

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

出处:http://blog.csdn.net/lmj623565791/article/details/37936275 1.概述 众所周知,Activity在不明确指定屏幕方向和configChanges时,当用户旋转屏幕会重新启动.当然了,应对这种情况,Android给出了几种方案: a.如果是少量数据,可以通过onSaveInstanceState()和onRestoreInstanceState()进行保存与恢复. Android会在销毁你的Activity之前调用onSaveInst