博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
我的Android进阶之旅------>Android利用Sensor(传感器)实现水平仪功能的小例
阅读量:6596 次
发布时间:2019-06-24

本文共 4918 字,大约阅读时间需要 16 分钟。

   

   这里介绍的水平仪,指的是比较传统的气泡水平仪,在一个透明圆盘内充满液体,液体中留有一个气泡,当一端翘起时,该气泡就会浮向翘起的一端。

   
利用方向传感器返回的第一个参数,实现了一个指南针小应用。
 (地址:http://blog.csdn.net/ouyang_peng/article/details/8801204)
   接下来,我们利用返回的第二、三个参数实现该水平仪。因为第二个参数,反映底部翘起的角度(当顶部翘起时为负值),第三个参数可以反映右侧翘起的角度(当左侧翘起时为负值)。根据这两个角度就可以开发水平仪,实现手机哪端翘起,气泡就浮向哪端,这也是水平仪的实现思想。本实例来自于《疯狂Android讲义》
先来看下运行效果:
该程序自定义了一个View,用来绘制透明圆盘和气泡,其中气泡的位置会动态改变。自定义View代码如下:
MyView.java
package org.crazyit.sensor;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.util.AttributeSet;import android.view.View;public class MyView extends View {	// 定义水平仪仪表盘图片	Bitmap back;	// 定义水平仪中的气泡图标	Bitmap bubble;	// 定义水平仪中气泡 的X、Y座标	int bubbleX, bubbleY;	public MyView(Context context, AttributeSet attrs) {		super(context, attrs);		// 加载水平仪图片和气泡图片		back = BitmapFactory.decodeResource(getResources(), R.drawable.back);		bubble = BitmapFactory				.decodeResource(getResources(), R.drawable.bubble);	}	@Override	protected void onDraw(Canvas canvas) {		super.onDraw(canvas);		// 绘制水平仪表盘图片		canvas.drawBitmap(back, 0, 0, null);		// 根据气泡座标绘制气泡		canvas.drawBitmap(bubble, bubbleX, bubbleY, null);	}}
布局文件 main.xml
bubble.png    
back.png   
Gradienter.java
package org.crazyit.sensor;import android.app.Activity;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;import android.os.Bundle;public class Gradienter extends Activity implements SensorEventListener {	// 定义水平仪的仪表盘	MyView show;	// 定义水平仪能处理的最大倾斜角,超过该角度,气泡将直接在位于边界。	int MAX_ANGLE = 30;	// 定义Sensor管理器	SensorManager mSensorManager;	@Override	public void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.main);		// 获取水平仪的主组件		show = (MyView) findViewById(R.id.show);		// 获取传感器管理服务		mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);	}	@Override	public void onResume() {		super.onResume();		// 为系统的方向传感器注册监听器		mSensorManager.registerListener(this,				mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),				SensorManager.SENSOR_DELAY_GAME);	}	@Override	protected void onPause() {		// 取消注册		mSensorManager.unregisterListener(this);		super.onPause();	}	@Override	protected void onStop() {		// 取消注册		mSensorManager.unregisterListener(this);		super.onStop();	}	@Override	public void onAccuracyChanged(Sensor sensor, int accuracy) {	}	@Override	public void onSensorChanged(SensorEvent event) {		float[] values = event.values;		// 获取触发event的传感器类型		int sensorType = event.sensor.getType();		switch (sensorType) {		case Sensor.TYPE_ORIENTATION:			// 获取与Y轴的夹角			float yAngle = values[1];			// 获取与Z轴的夹角			float zAngle = values[2];			// 气泡位于中间时(水平仪完全水平),气泡的X、Y座标			int x = (show.back.getWidth() - show.bubble.getWidth()) / 2;			int y = (show.back.getHeight() - show.bubble.getHeight()) / 2;			// 如果与Z轴的倾斜角还在最大角度之内			if (Math.abs(zAngle) <= MAX_ANGLE) {				// 根据与Z轴的倾斜角度计算X座标的变化值(倾斜角度越大,X座标变化越大)				int deltaX = (int) ((show.back.getWidth() - show.bubble						.getWidth()) / 2 * zAngle / MAX_ANGLE);				x += deltaX;			}			// 如果与Z轴的倾斜角已经大于MAX_ANGLE,气泡应到最左边			else if (zAngle > MAX_ANGLE) {				x = 0;			}			// 如果与Z轴的倾斜角已经小于负的MAX_ANGLE,气泡应到最右边			else {				x = show.back.getWidth() - show.bubble.getWidth();			}			// 如果与Y轴的倾斜角还在最大角度之内			if (Math.abs(yAngle) <= MAX_ANGLE) {				// 根据与Y轴的倾斜角度计算Y座标的变化值(倾斜角度越大,Y座标变化越大)				int deltaY = (int) ((show.back.getHeight() - show.bubble						.getHeight()) / 2 * yAngle / MAX_ANGLE);				y += deltaY;			}			// 如果与Y轴的倾斜角已经大于MAX_ANGLE,气泡应到最下边			else if (yAngle > MAX_ANGLE) {				y = show.back.getHeight() - show.bubble.getHeight();			}			// 如果与Y轴的倾斜角已经小于负的MAX_ANGLE,气泡应到最右边			else {				y = 0;			}			// 如果计算出来的X、Y座标还位于水平仪的仪表盘内,更新水平仪的气泡座标			if (isContain(x, y)) {				show.bubbleX = x;				show.bubbleY = y;			}			// 通知系统重回MyView组件			show.postInvalidate();			break;		}	}	// 计算x、y点的气泡是否处于水平仪的仪表盘内	private boolean isContain(int x, int y) {		// 计算气泡的圆心座标X、Y		int bubbleCx = x + show.bubble.getWidth() / 2;		int bubbleCy = y + show.bubble.getWidth() / 2;		// 计算水平仪仪表盘的圆心座标X、Y		int backCx = show.back.getWidth() / 2;		int backCy = show.back.getWidth() / 2;		// 计算气泡的圆心与水平仪仪表盘的圆心之间的距离。		double distance = Math.sqrt((bubbleCx - backCx) * (bubbleCx - backCx)				+ (bubbleCy - backCy) * (bubbleCy - backCy));		// 若两个圆心的距离小于它们的半径差,即可认为处于该点的气泡依然位于仪表盘内		if (distance < (show.back.getWidth() - show.bubble.getWidth()) / 2) {			return true;		} else {			return false;		}	}}
AndroidManifest.xml
PS:请在真机环境下运行此程序,如果在模拟器下运行,可能没效果
 
 
                           
====================================================================================

  作者:欧阳鹏  欢迎转载,与人分享是进步的源泉!

  转载请保留原文地址

====================================================================================

 

转载于:https://www.cnblogs.com/ouyangpeng/p/8538055.html

你可能感兴趣的文章
如何在tomcat下用EL表达式${param.xxx}属性获取parameter中文避免乱码
查看>>
线性表之栈与队列
查看>>
Git撤销修改
查看>>
项目管理实施流程(八)系统运维
查看>>
ipv4及ipv6及tcp的头部结构
查看>>
win7图片目录位置
查看>>
Maven
查看>>
FastDFS之集群部署
查看>>
Centos6.3系统语言设置
查看>>
我的友情链接
查看>>
javascript不可用的问题探究
查看>>
[置顶] jQuery乱谈(五)
查看>>
have sth done/doing的区别
查看>>
paste用法
查看>>
《java开发实战经典》读书笔记——第3章 Java基础程序设计之数据类型划分20151026...
查看>>
C. Tanya and Toys_模拟
查看>>
Swift 表达式
查看>>
JS实例(一)百度前端技术学院任务(十三)
查看>>
DEBUG(2)--函数的输入参数要做适当的检查
查看>>
js适配器模式
查看>>