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和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...
随机推荐
- 一个小的程序--实现中英文切换(纯css)
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...
- .NET基础拾遗(7)多线程开发基础3
一.如何使用异步模式? 异步模式是在处理流类型时经常采用的一种方式,其应用的领域相当广阔,包括读写文件.网络传输.读写数据库,甚至可以采用异步模式来做任何计算工作.相对于手动编写线程代码,异步模式是一 ...
- HTML基础总结<头部>
重点摘录:HTML head 元素 标签 描述 <head> 定义了文档的信息 <title> 定义了文档的标题 <base> 定义了页面链接标签的默认链接地址 & ...
- js生成随机数的方法小结
js生成随机数主要用到了内置的Math对象的random()方法.用法如:Math.random().它返回的是一个 0 ~ 1 之间的随机数.有了这么一个方法,那生成任意随机数就好理解了.比如实际中 ...
- c笔试题(1)
1.sizeof和strlen的区别 #include<stdio.h> #include<string.h> int main() { char a[10] = " ...
- .net转php laraval框架学习系列(三)项目实战---Route&Controllers
本章来学习laravel的路由 一个简单的路由列子 Route::get('/', function() { return 'Hello World'; }); 路由的写法和Node的风格很相似.上面 ...
- uC/OS 的任务调度解析 (转)
uC/OS 的任务调度解析 1.任务调度器启动之后(初始化,主要是TCB的初始化),就可以创建任务,开始任务调度了,实际上第一个任务准确的说不是进行任务切换,而是进行启动当前最高优先级任务.uC/OS ...
- 红帽(Red Hat Linux)下SVN服务器的安装与配置
转:http://www.cnblogs.com/xd502djj/archive/2011/01/21/1941404.html 第一章 安装 1. 采用源文件编译安装.源文件共两个,为:subve ...
- substr vs substring
javascript(js)中的 substring和substr方法 Posted on 2009-02-26 14:14 chinaifne 阅读(33698) 评论(0) 编辑 收藏 1.sub ...
- 页面正在载入js
页面显示(pageshow)和页面隐藏(pagehide)事件 http://blog.163.com/jiang_tao_2010/blog/static/121126890200911403336 ...