指南针

来源:互联网 发布:mac电脑笔记本 编辑:程序博客网 时间:2024/04/28 17:56

一 原理分析

      移动设备中一般都包括方向传感器,而方向传感器是用于感应设备的摆放状态,方向传感器可以为我们返回三个角度,这样一来就可以知道设备的摆放状态,下面逐一说明下这三个角度:
第一个角度:表示手机顶部朝向正北方的夹角。当手机绕着Z轴旋转时,该角度值发生改变。例如当该角度为0时,表明手机顶部朝向正北;该角度为90时,表明手机顶部朝向正东;该角度为180时,表示手机顶部朝向正南;该角度为270时,表示手机顶部朝向正西。
第二个角度:表示手机顶部或尾部翘起的角度。当手机绕着X轴旋转时,该角度发生变化。该角度的取值范围为-180~180.假设将手机屏幕朝上水平放在桌面上,如果桌面是完全水平的,该角度值应该为0。例如从手机顶部开始抬起,直到沿着X轴旋转180度(此时手机屏幕朝下),在这个过程该角度会从0变化到-180度。也就是说,从手机顶部抬起时,该角度会逐渐变小,最后等于-180;如果手机从底部开始抬起,直到将手机沿着X轴旋转180度(此时手机屏幕朝下),该角度的值会从0变化到180。也就是说,从手机底部抬起时,该角度的值会逐渐增大,直到180。
第三个角度:表示手机左侧或者右侧翘起的角度。当手机绕着Y轴旋转时,该角度值发生变化。该角度值范围是-90~90.例如将手机左侧逐渐抬起,直到将手机沿着Y轴旋转90度(手机与桌面垂直),在这个选择的过程中,该角度会从0变到-90。也就是说,从手机左侧抬起,该角度的值会逐渐减小,直到等于-90;如果从手机右侧开始抬起,直到将手机沿着Y轴旋转90度(手机与桌面垂直),该角度值会从0变化到90。也就是说,从手机右侧抬起时,该角度的值会逐渐增大,直到等于90。【这部分内容来自《疯狂Android讲义》】
      那么指南针是如何实现的呢?由于方向传感器第一个角度值是绕着Z轴旋转而来的,即手机顶部与正北方向的夹角,我们可以通过它来开发出指南针。

二 代码实现

1 获取传感器管理服务类
sm = (SensorManager) getSystemService(SENSOR_SERVICE);
2 获取当前设备支持的所有传感器
//获取手机上支持的所有传感器
deviceSensors = sm.getSensorList(Sensor.TYPE_ALL);
3 判断当前设备是否支持方向传感器,如果有就获取方向传感器
if (!check(Sensor.TYPE_ORIENTATION)) {
Toast.makeText(this, "当前设备不支持方向传感器", Toast.LENGTH_SHORT).show();
}else {
orientation = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
判断方法实现如下:
/**
* 检测设备是否支持某类型的传感器
*
* @param type 传感器的类型
* @return true 当前设备支持该类型的传感器 否则不支持
*/
private boolean check(int type) {
Iterator<Sensor> iterator = deviceSensors.iterator();
while (iterator.hasNext()) {
Sensor sensor = iterator.next();
if (sensor.getType() == type) {
return true;
}
}
return false;
}
4 给方向传感器设置监听
@Override
protected void onResume() {
super.onResume();
if (orientation != null){
sm.registerListener(this,orientation,SensorManager.SENSOR_DELAY_FASTEST);
}
}
说明,这里直接使Activity实现了SensorEventListener接口。
5 实现SensorEventListener的抽象方法获取手机绕Z轴的旋转角度,根据该角度值创建旋转动画
@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
switch (event.sensor.getType()){
case Sensor.TYPE_ORIENTATION:
//获取绕Z轴旋转角度
float degreeZ = event.values[0];
//创建旋转动画
RotateAnimation ra = new RotateAnimation(currentDegree,-degreeZ,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
ra.setDuration(200);
img_com.startAnimation(ra);
currentDegree = - degreeZ ;
break;
}
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}
6 在Activity的onStop的方法中反注册监听
@Override
protected void onStop() {
super.onStop();
if (orientation != null){
sm.unregisterListener(this);
}
}
至此实现了简单指南针。下面贴出完整代码:
public class CompassActivity extends AppCompatActivity implements SensorEventListener {

private ImageView img_com;
private SensorManager sm;
private List<Sensor> deviceSensors;
/**方向传感器*/
private Sensor orientation;
/** 记录指南针图片旋转过的角度*/
float currentDegree = 0f;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_compass);
img_com = (ImageView) findViewById(R.id.img_com);
sm = (SensorManager) getSystemService(SENSOR_SERVICE);
//获取手机上支持的所有传感器
deviceSensors = sm.getSensorList(Sensor.TYPE_ALL);
if (!check(Sensor.TYPE_ORIENTATION)) {
Toast.makeText(this, "当前设备不支持方向传感器", Toast.LENGTH_SHORT).show();
}else {
orientation = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}

}

@Override
protected void onResume() {
super.onResume();
if (orientation != null){
sm.registerListener(this,orientation,SensorManager.SENSOR_DELAY_FASTEST);
}
}

@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
switch (event.sensor.getType()){
case Sensor.TYPE_ORIENTATION:
//获取绕Z轴旋转角度
float degreeZ = event.values[0];
//创建旋转动画
RotateAnimation ra = new RotateAnimation(currentDegree,-degreeZ,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
ra.setDuration(200);
img_com.startAnimation(ra);
currentDegree = - degreeZ ;
break;
}
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}


/**
* 检测设备是否支持某类型的传感器
*
* @param type 传感器的类型
* @return true 当前设备支持该类型的传感器 否则不支持
*/
private boolean check(int type) {
Iterator<Sensor> iterator = deviceSensors.iterator();
while (iterator.hasNext()) {
Sensor sensor = iterator.next();
if (sensor.getType() == type) {
return true;
}
}
return false;
}


@Override
protected void onStop() {
super.onStop();
if (orientation != null){
sm.unregisterListener(this);
}
}

}
完整项目示例代码





原创粉丝点击