• Android 自定义UI--指南针


     有了之前的基础,下面开始实现一个简单的指南针。首先来看一下效果图,

        我们可以粗略将这个指南针分为三个部分,一是圆形背景,二是刻度,三是文本。那么在写代码的时候,就可以声明三个Paint画笔来画以上三个物体。代码如下:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. package com.example.apptest;  
    2.   
    3. import android.content.Context;  
    4. import android.graphics.Canvas;  
    5. import android.graphics.Color;  
    6. import android.graphics.Paint;  
    7. import android.util.AttributeSet;  
    8. import android.util.Log;  
    9. import android.view.View;  
    10.   
    11. /**  
    12.  * 指南针  
    13.  *   
    14.  */  
    15. class CompassView extends View {  
    16.       
    17.     //刻度画笔  
    18.     private Paint markerPaint;  
    19.     //文本画笔  
    20.     private Paint textPaint;  
    21.     //圆形画笔  
    22.     private Paint circlePaint;  
    23.     //字符串  
    24.     private String northString;  
    25.     //字符串  
    26.     private String eastString;  
    27.     //字符串  
    28.     private String southString;  
    29.     //字符串  
    30.     private String westString;  
    31.     //文本高度  
    32.     private int textHeight;  
    33.     //轴  
    34.     private float bearing;  
    35.     /**  
    36.      *   
    37.      * @param _bearing  
    38.      */  
    39.     public void setBearing(float _bearing) {  
    40.         bearing = _bearing;  
    41.     }  
    42.     /**  
    43.      *   
    44.      * @return  
    45.      */  
    46.     public float getBearing() {  
    47.         return bearing;  
    48.     }  
    49.   
    50.     public CompassView(Context context) {  
    51.         super(context);  
    52.         initCompassView();  
    53.     }  
    54.   
    55.     public CompassView(Context context, AttributeSet attrs) {  
    56.         super(context, attrs);  
    57.         initCompassView();  
    58.     }  
    59.   
    60.     public CompassView(Context context, AttributeSet attrs, int defaultStyle) {  
    61.         super(context, attrs, defaultStyle);  
    62.         initCompassView();  
    63.     }  
    64.   
    65.     protected void initCompassView() {  
    66.         setFocusable(true);  
    67.   
    68.         // 东西南北  
    69.         northString = "北";  
    70.         eastString = "东";  
    71.         southString = "南";  
    72.         westString = "西";  
    73.         // 设置实心圆画笔  
    74.         circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
    75.         circlePaint.setColor(Color.BLACK);  
    76.         circlePaint.setStrokeWidth(1);  
    77.         circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);  
    78.         // 设置线条画笔 刻度  
    79.         markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
    80.         markerPaint.setColor(Color.RED);  
    81.         // 设置坐标画笔 东西南北 度数  
    82.         textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
    83.         textPaint.setColor(Color.WHITE);  
    84.         // 设置文字高度  
    85.         textHeight = (int) textPaint.measureText("yY");  
    86.         Log.i("textHeight", textHeight+"");  
    87.   
    88.     }  
    89.   
    90.     @Override  
    91.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
    92.         int measuredWidth = measure(widthMeasureSpec);  
    93.         int measuredHeight = measure(heightMeasureSpec);  
    94.         int d = Math.min(measuredWidth, measuredHeight);  
    95.         setMeasuredDimension(d, d);  
    96.     }  
    97.     /**  
    98.      * @category   
    99.      * @param measureSpec  
    100.      * @return  
    101.      */  
    102.     private int measure(int measureSpec) {  
    103.         int result = 0;  
    104.         int specMode = MeasureSpec.getMode(measureSpec);  
    105.         int specSize = MeasureSpec.getSize(measureSpec);  
    106.   
    107.         if (specMode == MeasureSpec.UNSPECIFIED) {  
    108.             result = 200;  
    109.         } else {  
    110.             result = specSize;  
    111.         }  
    112.         return result;  
    113.     }  
    114.   
    115.     @Override  
    116.     protected void onDraw(Canvas canvas) {  
    117.         // 圆心坐标  
    118.         int px = getMeasuredWidth() / 2;  
    119.         Log.i("px", px+"");  
    120.         int py = getMeasuredHeight() / 2;  
    121.         Log.i("py", py+"");  
    122.         // 半径 取最小值  
    123.         int radius = Math.min(px, py);  
    124.         Log.i("radius", radius+"");  
    125.         // 画圆  
    126.         canvas.drawCircle(px, py, radius, circlePaint);  
    127.         canvas.save();  
    128.         canvas.rotate(-bearing, px, py);  
    129.         // 东西南北 坐标位置  
    130.         int textWidth = (int) textPaint.measureText("W");  
    131.         Log.i("textWidth", textWidth+"");  
    132.         int cardinalX = px - textWidth / 2;  
    133.         Log.i("cardinalX", cardinalX+"");  
    134.         int cardinalY = py - radius + textHeight;  
    135.         Log.i("cardinalY", cardinalY+"");  
    136.         //画24个刻度  
    137.         for (int i = 0; i 24; i++) {  
    138.             //画刻度  
    139.             canvas.drawLine(px, py - radius, px, py - radius + 10, markerPaint);  
    140.             canvas.save();  
    141.             //移动原点textHeight距离 开始画东西南北以及度数  
    142.             canvas.translate(0, textHeight);  
    143.             //判断如果满足条件画东西南北  
    144.             if (i % 6 == 0) {  
    145.                 String dirString = "";  
    146.                 switch (i) {  
    147.                 case (0): {  
    148.                     dirString = northString;  
    149.                     // 画指南针  
    150.                     int arrowY = 2 * textHeight;  
    151.                     canvas.drawLine(px, arrowY, px - 5, 3 * textHeight,  
    152.                             markerPaint);  
    153.                     canvas.drawLine(px, arrowY, px + 5, 3 * textHeight,  
    154.                             markerPaint);  
    155.                     break;  
    156.                 }  
    157.                 case (6):  
    158.                     dirString = eastString;  
    159.                     break;  
    160.                 case (12):  
    161.                     dirString = southString;  
    162.                     break;  
    163.                 case (18):  
    164.                     dirString = westString;  
    165.                     break;  
    166.                 }  
    167.                 //画东西南北  
    168.                 canvas.drawText(dirString, cardinalX, cardinalY, textPaint);  
    169.                   
    170.             }else if (i % 3 == 0) {//判断如果满足条件画4个度数  
    171.                 String angle = String.valueOf(i * 15);  
    172.                 float angleTextWidth = textPaint.measureText(angle);  
    173.   
    174.                 int angleTextX = (int) (px - angleTextWidth / 2);  
    175.                 int angleTextY = py - radius + textHeight;  
    176.                 //画弧度数  
    177.                 canvas.drawText(angle, angleTextX, angleTextY, textPaint);  
    178.             }  
    179.             canvas.restore();  
    180.             //每隔15度旋转一下  
    181.             canvas.rotate(15, px, py);  
    182.         }  
    183.         canvas.restore();  
    184.     }  
    185. }  

        这个例子中,多了一个measure过程,重写了OnMeasure()过程,用于计算View的大小。先不细说这个,下面重点说一下如何画图的。背景很简单,不多说,难点还是在于刻度以及文字的实现。我们知道,画文本可以使用drawText()方法,画刻度也就是画直线,可以使用drawLine()方法。那关键问题就是在哪个位置画刻度以及文本。本例子中,圆形的大小取决于屏幕的宽度,可以看到圆形的直接就是屏幕的宽度。画刻度线也是从圆心坐标开始的,直接使用drawLine()方法。还有一个地方需要注意就是东西南北以及刻度的文字是移动了一段距离后开始绘制的,使用的方法就是translate(),在画完14个刻度之后调用这个方法。

  • 相关阅读:
    ionic+cordova开发!
    npm安装出错的时候,如何使用国内的镜像!--解决办法
    wamp环境解决局域网不能访问的问题!
    flex弹性布局属性详解!
    JS判断当前是否是IE浏览器,并返回时IE几?
    thinkphp---手机访问切换模板!
    thinkCMF的使用!
    thinkphp5在集成环境目录访问权限问题
    微信小程序 --- 下拉刷新上拉加载
    jQuery --- 利用a标签的download属性下载文件!
  • 原文地址:https://www.cnblogs.com/dongweiq/p/4290340.html
Copyright © 2020-2023  润新知