Android 自定义UI--指南针
有了之前的基础,下面开始实现一个简单的指南针。首先来看一下效果图,
我们可以粗略将这个指南针分为三个部分,一是圆形背景,二是刻度,三是文本。那么在写代码的时候,就可以声明三个Paint画笔来画以上三个物体。代码如下:
- package com.example.apptest;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.View;
- /**
- * 指南针
- *
- */
- class CompassView extends View {
- //刻度画笔
- private Paint markerPaint;
- //文本画笔
- private Paint textPaint;
- //圆形画笔
- private Paint circlePaint;
- //字符串
- private String northString;
- //字符串
- private String eastString;
- //字符串
- private String southString;
- //字符串
- private String westString;
- //文本高度
- private int textHeight;
- //轴
- private float bearing;
- /**
- *
- * @param _bearing
- */
- public void setBearing(float _bearing) {
- bearing = _bearing;
- }
- /**
- *
- * @return
- */
- public float getBearing() {
- return bearing;
- }
- public CompassView(Context context) {
- super(context);
- initCompassView();
- }
- public CompassView(Context context, AttributeSet attrs) {
- super(context, attrs);
- initCompassView();
- }
- public CompassView(Context context, AttributeSet attrs, int defaultStyle) {
- super(context, attrs, defaultStyle);
- initCompassView();
- }
- protected void initCompassView() {
- setFocusable(true);
- // 东西南北
- northString = "北";
- eastString = "东";
- southString = "南";
- westString = "西";
- // 设置实心圆画笔
- circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- circlePaint.setColor(Color.BLACK);
- circlePaint.setStrokeWidth(1);
- circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
- // 设置线条画笔 刻度
- markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- markerPaint.setColor(Color.RED);
- // 设置坐标画笔 东西南北 度数
- textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- textPaint.setColor(Color.WHITE);
- // 设置文字高度
- textHeight = (int) textPaint.measureText("yY");
- Log.i("textHeight", textHeight+"");
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int measuredWidth = measure(widthMeasureSpec);
- int measuredHeight = measure(heightMeasureSpec);
- int d = Math.min(measuredWidth, measuredHeight);
- setMeasuredDimension(d, d);
- }
- /**
- * @category
- * @param measureSpec
- * @return
- */
- private int measure(int measureSpec) {
- int result = 0;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
- if (specMode == MeasureSpec.UNSPECIFIED) {
- result = 200;
- } else {
- result = specSize;
- }
- return result;
- }
- @Override
- protected void onDraw(Canvas canvas) {
- // 圆心坐标
- int px = getMeasuredWidth() / 2;
- Log.i("px", px+"");
- int py = getMeasuredHeight() / 2;
- Log.i("py", py+"");
- // 半径 取最小值
- int radius = Math.min(px, py);
- Log.i("radius", radius+"");
- // 画圆
- canvas.drawCircle(px, py, radius, circlePaint);
- canvas.save();
- canvas.rotate(-bearing, px, py);
- // 东西南北 坐标位置
- int textWidth = (int) textPaint.measureText("W");
- Log.i("textWidth", textWidth+"");
- int cardinalX = px - textWidth / 2;
- Log.i("cardinalX", cardinalX+"");
- int cardinalY = py - radius + textHeight;
- Log.i("cardinalY", cardinalY+"");
- //画24个刻度
- for (int i = 0; i < 24; i++) {
- //画刻度
- canvas.drawLine(px, py - radius, px, py - radius + 10, markerPaint);
- canvas.save();
- //移动原点textHeight距离 开始画东西南北以及度数
- canvas.translate(0, textHeight);
- //判断如果满足条件画东西南北
- if (i % 6 == 0) {
- String dirString = "";
- switch (i) {
- case (0): {
- dirString = northString;
- // 画指南针
- int arrowY = 2 * textHeight;
- canvas.drawLine(px, arrowY, px - 5, 3 * textHeight,
- markerPaint);
- canvas.drawLine(px, arrowY, px + 5, 3 * textHeight,
- markerPaint);
- break;
- }
- case (6):
- dirString = eastString;
- break;
- case (12):
- dirString = southString;
- break;
- case (18):
- dirString = westString;
- break;
- }
- //画东西南北
- canvas.drawText(dirString, cardinalX, cardinalY, textPaint);
- }else if (i % 3 == 0) {//判断如果满足条件画4个度数
- String angle = String.valueOf(i * 15);
- float angleTextWidth = textPaint.measureText(angle);
- int angleTextX = (int) (px - angleTextWidth / 2);
- int angleTextY = py - radius + textHeight;
- //画弧度数
- canvas.drawText(angle, angleTextX, angleTextY, textPaint);
- }
- canvas.restore();
- //每隔15度旋转一下
- canvas.rotate(15, px, py);
- }
- canvas.restore();
- }
- }
这个例子中,多了一个measure过程,重写了OnMeasure()过程,用于计算View的大小。先不细说这个,下面重点说一下如何画图的。背景很简单,不多说,难点还是在于刻度以及文字的实现。我们知道,画文本可以使用drawText()方法,画刻度也就是画直线,可以使用drawLine()方法。那关键问题就是在哪个位置画刻度以及文本。本例子中,圆形的大小取决于屏幕的宽度,可以看到圆形的直接就是屏幕的宽度。画刻度线也是从圆心坐标开始的,直接使用drawLine()方法。还有一个地方需要注意就是东西南北以及刻度的文字是移动了一段距离后开始绘制的,使用的方法就是translate(),在画完14个刻度之后调用这个方法。
Android 自定义UI--指南针的更多相关文章
- android自定义UI模板图文详解
不知道大家在实际开发中有没有自定义过UI模板?今天花时间研究了一下android中自定义UI模板,与大家分享一下. 每个设计良好的App都是自定义标题栏,在自定义标题栏的过程中大部分人可能都是自定义一 ...
- Android自定义UI的实现和应用
在Android项目开发中,不可避免的要遇到自定义的UI,用较好的体验去讨好UED妹子和交互设计师手下留情~几个迭代下来,遇到了不少这样的要求,有简单有复杂.最好的实现方案就是讲业务和UI隔离,封装成 ...
- Android自定义UI模板
第一步:自定义xml属性 新建一个android项目,在values文件夹中新建一个atts.xml的文件,在这个xml文件中声明我们一会在使用自定义控件时候需要指明的属性.atts.xml < ...
- android自定义View之NotePad出鞘记
现在我们的手机上基本都会有一个记事本,用起来倒也还算方便,记事本这种东东,如果我想要自己实现,该怎么做呢?今天我们就通过自定义View的方式来自定义一个记事本.OK,废话不多说,先来看看效果图. 整个 ...
- Android开源的精美日历控件,热插拔设计的万能自定义UI
Android开源的精美日历控件,热插拔设计的万能自定义UI UI框架应该逻辑与界面实现分离,该日历控件使用了热插拔的设计 ,简单几步即可实现你需要的UI效果,热插拔的思想是你提供你的实现,我提供我的 ...
- Android自定义View和控件之一-定制属于自己的UI
照例,拿来主义.我的学习是基于下面的三篇blog.前两是基本的流程,第三篇里有比较细致的绘制相关的属性.第4篇介绍了如何减少布局层次来提高效率. 1. 教你搞定Android自定义View 2. 教你 ...
- Android自定义View 画弧形,文字,并增加动画效果
一个简单的Android自定义View的demo,画弧形,文字,开启一个多线程更新ui界面,在子线程更新ui是不允许的,但是View提供了方法,让我们来了解下吧. 1.封装一个抽象的View类 B ...
- Android 自定义View合集
自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...
- Android 自定义View (五)——实践
前言: 前面已经介绍了<Android 自定义 view(四)-- onMeasure 方法理解>,那么这次我们就来小实践下吧 任务: 公司现有两个任务需要我完成 (1)监测液化天然气液压 ...
- [原] Android 自定义View步骤
例子如下:Android 自定义View 密码框 例子 1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...
随机推荐
- Java基础知识强化68:基本类型包装类之Character概述和Character常见方法
1. Character概述: public final class Character extends Object implements Serializable,Comparable<Ch ...
- 配置squid代理服务
1. 简述一下squid的用途?squid可以做代理和缓存服务器,而做代理时,可以分为正向代理和反向代理.正向代理用在企业办公环境中,企业员工上网通过代理来上网,代理的缓存功能可以为企业节省宝贵的带宽 ...
- (一)《Java编程思想》学习——按位运算符、移位运算符
(第三章) (一)按位运算符 按位逻辑运算符有: “与”(AND) & 1&1=1;1&0=0;0&0=0 “或”(OR) | 1|1=1;1|0=1;0 ...
- MVC---404页面配置
参考地址1:http://benfoster.io/blog/aspnet-mvc-custom-error-pages 参考地址2:https://msdn.microsoft.com/en-us/ ...
- O、Ω、Θ表示
转载,原网址为:http://book.2cto.com/201211/8127.html 对于任何数学函数,这三个记号可以用来度量其“渐近表现”,即当趋于无穷大时的阶的情况,这是算法分析中非常重要的 ...
- log4j.property配置
# 1. 日志等级 FATAL=0; ERROR=3; WARN=4; INFO=6; DEBUG=7; # 2. Appender 为日志输出目的地,Log4j提供的appender有以下几种# o ...
- C#模拟登录的htmlHelper类
public class HTMLHelper { /// <summary> /// 获取CooKie /// /// </summary> /// /// <para ...
- develop process
-f Option is dangerous, make sure that only do this on your own branch # When you starting coding at ...
- 标准程序员系列-Github篇-初始化一个代码仓库
下面将一步步介绍怎样使用GitHub来初始化一个项目的版本控制仓库: 1. 到GitHub上注册自己的账号:https://github.com/ 2. 创建第一个代码仓库一个仓库相当于一个项目的代码 ...
- Page.ClientScript.RegisterStartupScript函数的使用
Page.ClientScript.RegisterStartupScript(type,key,script,addScriptTags);type要注册的启动脚本的类型.key要注册的启动脚本的键 ...