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

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

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

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

Android 自定义UI--指南针的更多相关文章

  1. android自定义UI模板图文详解

    不知道大家在实际开发中有没有自定义过UI模板?今天花时间研究了一下android中自定义UI模板,与大家分享一下. 每个设计良好的App都是自定义标题栏,在自定义标题栏的过程中大部分人可能都是自定义一 ...

  2. Android自定义UI的实现和应用

    在Android项目开发中,不可避免的要遇到自定义的UI,用较好的体验去讨好UED妹子和交互设计师手下留情~几个迭代下来,遇到了不少这样的要求,有简单有复杂.最好的实现方案就是讲业务和UI隔离,封装成 ...

  3. Android自定义UI模板

    第一步:自定义xml属性 新建一个android项目,在values文件夹中新建一个atts.xml的文件,在这个xml文件中声明我们一会在使用自定义控件时候需要指明的属性.atts.xml < ...

  4. android自定义View之NotePad出鞘记

    现在我们的手机上基本都会有一个记事本,用起来倒也还算方便,记事本这种东东,如果我想要自己实现,该怎么做呢?今天我们就通过自定义View的方式来自定义一个记事本.OK,废话不多说,先来看看效果图. 整个 ...

  5. Android开源的精美日历控件,热插拔设计的万能自定义UI

    Android开源的精美日历控件,热插拔设计的万能自定义UI UI框架应该逻辑与界面实现分离,该日历控件使用了热插拔的设计 ,简单几步即可实现你需要的UI效果,热插拔的思想是你提供你的实现,我提供我的 ...

  6. Android自定义View和控件之一-定制属于自己的UI

    照例,拿来主义.我的学习是基于下面的三篇blog.前两是基本的流程,第三篇里有比较细致的绘制相关的属性.第4篇介绍了如何减少布局层次来提高效率. 1. 教你搞定Android自定义View 2. 教你 ...

  7. Android自定义View 画弧形,文字,并增加动画效果

    一个简单的Android自定义View的demo,画弧形,文字,开启一个多线程更新ui界面,在子线程更新ui是不允许的,但是View提供了方法,让我们来了解下吧. 1.封装一个抽象的View类   B ...

  8. Android 自定义View合集

    自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...

  9. Android 自定义View (五)——实践

    前言: 前面已经介绍了<Android 自定义 view(四)-- onMeasure 方法理解>,那么这次我们就来小实践下吧 任务: 公司现有两个任务需要我完成 (1)监测液化天然气液压 ...

  10. [原] Android 自定义View步骤

    例子如下:Android 自定义View 密码框 例子 1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...

随机推荐

  1. [转]Swift编程风格指南

    语言 使用美式英语拼写以匹配苹果公司的API 优选: var color = "red" 不建议使用: var colour = "red" 间隔 使用2个空格 ...

  2. div滚动条,可以自由的给滚动条定义背景,上下按钮,当然不仅仅是颜色,连图片当背景也可以。

    可以自由的给滚动条定义背景,上下按钮,当然不仅仅是颜色,连图片当背景也可以.支持鼠标滚轮,点击滚动条滚轴定位,上下按钮久按加速,兼容firefox,谷歌 下载地址

  3. sql语句各种九九乘法表

    下面用while 和 if 条件写的SQL语句的四种九九乘法表 --9x9 左下角 ) BEGIN SET @S='' WHILE @J<=@I BEGIN )))))) END PRINT @ ...

  4. css3滚动提示

    <css揭秘>书中,滚动提示的实现 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  5. Linux平台Makefile文件的编写基础篇(转)

    目的:       基本掌握了 make 的用法,能在Linux系统上编程.环境:       Linux系统,或者有一台Linux服务器,通过终端连接.一句话:有Linux编译环境.准备:      ...

  6. Java Tips: 使用Pattern.split替代String.split

    String.split方法很常用,用于切割字符串,split传入的参数是正则表达式,它的内部是每次都comiple正则表达式,再调用Pattern.split方法: public String[] ...

  7. SQL建模错误--逗号分隔值

    最近帮一个客户分析SQL语句的问题,大致经过如下 场景: 委托方有一个用于追踪他们产品的系统,每个产品都会卖给许多客户:但是客户又被从业务上分成两类,一类是带有合作伙伴性质的,这个 合作伙伴通常会给予 ...

  8. python的工作记录B

    这次很强了.就差最后一步,判断一下SVN的版本是否是真的库里的. #!/usr/bin/env python # -*- coding: utf-8 -*- import os,sys,command ...

  9. AsyncCTP &IdentityModel

    AsyncCTP.0.3.nupkg http://pan.baidu.com/s/1kVhPaYj Microsoft.IdentityModel.6.1.7600.16394  http://pa ...

  10. github如何删除一个repository(仓库)

    昨天有人问我如何删除自己创建的一个项目,我浏览了一下github网站,确实不太容易找到删除功能.这里介绍一下啊如何在github上删除一个repository 一:首先点击进入你要删除的reposit ...