android 加速度传感器妙用与自定义View

本节的实例是一个倾斜角度测量应用,它可以准确的测量出你手机与水平面的倾斜角度,使用的是android传感器里面的加速传感器。巧妙的运用了加速度传感器各个值所代表的物理意义,加上一个很简单的算法,就能测出倾斜角度。

角度值会随着手机的倾斜而准确显示,效果如图:


废话不多说直接上代码,上面有清楚的说明

  1. package sina.CreAmazing.angle_view;
  2. import android.app.Activity;
  3. import android.content.Context;
  4. import android.graphics.BitmapFactory;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.Paint;
  8. import android.hardware.Sensor;
  9. import android.hardware.SensorEvent;
  10. import android.hardware.SensorEventListener;
  11. import android.hardware.SensorManager;
  12. import android.os.Bundle;
  13. import android.util.DisplayMetrics;
  14. import android.util.Log;
  15. import android.view.View;
  16. public class AngleViewActivity extends Activity {
  17. /** Called when the activity is first created. */
  18. //声明一个SensorManager管理传感器,一个自定义的类MyView,在myView中绘制自己想要的图像
  19. private SensorManager sensorManager;
  20. private MyView myView;
  21. @Override
  22. public void onCreate(Bundle savedInstanceState) {
  23. super.onCreate(savedInstanceState);
  24. //实例化SensorManager
  25. sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
  26. //DisplayMetrics用于获取屏幕大小,再传递给myView方便绘制图形界面;
  27. DisplayMetrics display = new DisplayMetrics();
  28. getWindowManager().getDefaultDisplay().getMetrics(display);
  29. //构造一个MyView,display.widthPixels是当前屏幕的宽度,display.heightPixels是当前屏幕的高度
  30. myView = new MyView(this, display.widthPixels, display.heightPixels);
  31. //这里就不是在layout文件夹里面的布局文件了,直接就是我们的myView。
  32. setContentView(myView);
  33. }
  34. //在onResume(),onPause()中注册和解除监听器
  35. @Override
  36. protected void onResume() {
  37. super.onResume();
  38. sensorManager.registerListener(myView,
  39. sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
  40. SensorManager.SENSOR_DELAY_NORMAL);
  41. }
  42. @Override
  43. protected void onPause() {
  44. sensorManager.unregisterListener(myView);
  45. Log.i("unregister", "ok");
  46. super.onStop();
  47. }
  48. }
  49. //自定义的类MyView 因为要感应传感器所以实现SensorEventListener。
  50. class MyView extends View implements SensorEventListener {
  51. //float x = 0;
  52. //float y = 0;
  53. //z轴上的值是我们所需要的,z轴就是垂直于水平面的方向,当你水平放置手机是它的数值为10,当你垂直放置时它就为0.
  54. float z = 0;
  55. private float width;
  56. private float height;
  57. Paint p ;
  58. public MyView(Context context) {
  59. super(context);
  60. // TODO Auto-generated constructor stub
  61. }
  62. public MyView(Context context, float width, float height) {
  63. super(context);
  64. this.width = width;
  65. this.height = height;
  66. //得到一支画笔,设置基本属性
  67. p = new Paint();
  68. p.setStyle(Paint.Style.STROKE);
  69. }
  70. //在onDraw()方法中才是我们真正要画的东西,也就是真正显示在屏幕上的图像
  71. @Override
  72. protected void onDraw(Canvas canvas) {
  73. //首先绘制一张背景图片,图片是事先PS好的一张背景图。canvas就是画布的意思,我们需要用画笔 p 在画布canvas上画画。
  74. canvas.drawBitmap(
  75. BitmapFactory.decodeResource(getResources(), R.drawable.circle),
  76. 0, 0, p);
  77. //画背景后还要画文字,再对画笔进行设置。
  78. p.setTextSize(50);
  79. //所画的文字就是实际测得的角度,在这之前需要对z值进行转化也就是todegree()方法。
  80. canvas.drawText(todegree(z) + "°", width / 2 - 20, height / 2, p);
  81. //画完后再画一个圆圈,这个圆圈随着角度变化而变大变小。
  82. p.setColor(Color.RED);
  83. p.setStrokeWidth(2);
  84. canvas.drawCircle(width / 2, height / 2, 20 * z, p);
  85. }
  86. //如何把当前加速度的值转化为当前角度值呢?这需要一定的硬件基础才能明白其中的原理,不懂得同学可以看一些加速度传感器方面的书,关于加速度
  87. //传感器还有很多应用,比如速度的测量,位移的测量,这就需要更加复杂的算法了,这里就不再介绍
  88. private String todegree(float zz) {
  89. //首先判断加速度的值是否大于10,小于-10,这是因为在运动过程中加速是不稳定的,而我们要测的是在静止状态下的稳定值。
  90. if (zz > 10) {
  91. zz = 10;
  92. } else if (zz < -10) {
  93. zz = -10;
  94. }
  95. //acos(zz / 10)就能求出倾斜角度的弧度值。
  96. double r = Math.acos(zz / 10);
  97. //然后将弧度值转化为角度值
  98. int degree = (int) (r * 180 / Math.PI);
  99. //最后返回一个String
  100. return String.valueOf(degree);
  101. }
  102. @Override
  103. public void onSensorChanged(SensorEvent event) {
  104. // TODO Auto-generated method stub
  105. // x = event.values[0];
  106. // y = event.values[1];
  107. if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
  108. //获得z轴的加速度值
  109. z = event.values[2];
  110. }
  111. //调用此方法进行重绘
  112. invalidate();
  113. }
  114. @Override
  115. public void onAccuracyChanged(Sensor sensor, int accuracy) {
  116. // TODO Auto-generated method stub
  117. }
  118. }
package sina.CreAmazing.angle_view;

import android.app.Activity;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

public class AngleViewActivity extends Activity {
	/** Called when the activity is first created. */
	//声明一个SensorManager管理传感器,一个自定义的类MyView,在myView中绘制自己想要的图像
	private SensorManager sensorManager;
	private MyView myView;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//实例化SensorManager
		sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
		//DisplayMetrics用于获取屏幕大小,再传递给myView方便绘制图形界面;
		DisplayMetrics display = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(display);
		//构造一个MyView,display.widthPixels是当前屏幕的宽度,display.heightPixels是当前屏幕的高度
		myView = new MyView(this, display.widthPixels, display.heightPixels);
		//这里就不是在layout文件夹里面的布局文件了,直接就是我们的myView。
		setContentView(myView);
	}
	//在onResume(),onPause()中注册和解除监听器
	@Override
	protected void onResume() {
		super.onResume();

		sensorManager.registerListener(myView,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_NORMAL);
	}

	@Override
	protected void onPause() {

		sensorManager.unregisterListener(myView);
		Log.i("unregister", "ok");
		super.onStop();
	}

}

//自定义的类MyView 因为要感应传感器所以实现SensorEventListener。
class MyView extends View implements SensorEventListener {

	//float x = 0;
	//float y = 0;
	
	//z轴上的值是我们所需要的,z轴就是垂直于水平面的方向,当你水平放置手机是它的数值为10,当你垂直放置时它就为0.
	float z = 0;
	private float width;
	private float height;
	Paint p ;
	
	public MyView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	public MyView(Context context, float width, float height) {
		super(context);
		this.width = width;
		this.height = height;
		
		//得到一支画笔,设置基本属性
		p =  new Paint();
		p.setStyle(Paint.Style.STROKE);


	}
//在onDraw()方法中才是我们真正要画的东西,也就是真正显示在屏幕上的图像
	@Override
	protected void onDraw(Canvas canvas) {
//首先绘制一张背景图片,图片是事先PS好的一张背景图。canvas就是画布的意思,我们需要用画笔 p 在画布canvas上画画。		 
		canvas.drawBitmap(
				BitmapFactory.decodeResource(getResources(), R.drawable.circle),
				0, 0, p);
		//画背景后还要画文字,再对画笔进行设置。
		p.setTextSize(50);
		//所画的文字就是实际测得的角度,在这之前需要对z值进行转化也就是todegree()方法。
		canvas.drawText(todegree(z) + "°", width / 2 - 20, height / 2, p);
		//画完后再画一个圆圈,这个圆圈随着角度变化而变大变小。
		p.setColor(Color.RED);
		p.setStrokeWidth(2);
		canvas.drawCircle(width / 2, height / 2, 20 * z, p);

	}
//如何把当前加速度的值转化为当前角度值呢?这需要一定的硬件基础才能明白其中的原理,不懂得同学可以看一些加速度传感器方面的书,关于加速度
//传感器还有很多应用,比如速度的测量,位移的测量,这就需要更加复杂的算法了,这里就不再介绍	
	private String todegree(float zz) {
		//首先判断加速度的值是否大于10,小于-10,这是因为在运动过程中加速是不稳定的,而我们要测的是在静止状态下的稳定值。
		if (zz > 10) {
			zz = 10;
		} else if (zz < -10) {
			zz = -10;
		}
		//acos(zz / 10)就能求出倾斜角度的弧度值。
		double r = Math.acos(zz / 10);
		//然后将弧度值转化为角度值
		int degree = (int) (r * 180 / Math.PI);
		//最后返回一个String
		return String.valueOf(degree);
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		// TODO Auto-generated method stub
		// x = event.values[0];
		// y = event.values[1];
		
		if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
			//获得z轴的加速度值
			z = event.values[2];
		}
		
		//调用此方法进行重绘
		invalidate();
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub

	}

}


 

项目源码:

http://115.com/file/an9mk3ya#AngleView.rar


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值