zoukankan      html  css  js  c++  java
  • 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>

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

  • 相关阅读:
    第02组 Beta冲刺(4/5)
    第02组 Beta冲刺(3/5)
    第02组 Beta冲刺(2/5)
    第02组 Beta冲刺(1/5)
    第02组 Alpha事后诸葛亮
    第02组 Alpha冲刺(6/6)
    第02组 Alpha冲刺(5/6)
    第02组 Alpha冲刺(4/6)
    第02组 Alpha冲刺(3/6)
    2020系统综合实践1 微服务与Docker 基本入门
  • 原文地址:https://www.cnblogs.com/fuly550871915/p/4986821.html
Copyright © 2011-2022 走看看