Android传感器开发

Android的传感器开发

1.1 开发传感器应用

开发传感器的步骤如下:

调用Context的getSystemService(Context.SENSOR_SERVICE)方法获取SensorManager对象。

调用SensorManager的getDefaultSensor(int type)方法来获取指定类型的传感器。

一般在Activity的onResume()方法中调用SensorManager的registerListener()为指定传感器注册监听器即可。程序可以通过实现监听器即可获取传感器传回来的数据。

SersorManager提供的注册传感器的方法为registerListener(SensorListener listener, Sensor sensor, int rate)该方法中三个参数说明如下:

listener:监听传感器事件的监听器

sensor:传感器对象

rate:指定获取传感器数据的频率

rate可以获取传感器数据的频率,支持如下几个频率值:

SENSOR_DELAY_FASTEST:最快,延迟最小。

SENSOR_DELAY_GAME:适合游戏的频率。

SENSOR_DELAY_NORMAL:正常频率

SENSOR_DELAY_UI:适合普通用户界面的频率。

例:加速度传感器:

AccelerometerTest.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class AccelerometerTest extends Activity
     implements SensorEventListener
{
     // 定义系统的Sensor管理器
     SensorManager sensorManager;
     EditText etTxt1;
 
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.main);
         // 获取程序界面上的文本框组件
         etTxt1 = (EditText) findViewById(R.id.txt1);
         // 获取系统的传感器管理服务
         sensorManager = (SensorManager) getSystemService(
             Context.SENSOR_SERVICE);
     }
 
     @Override
     protected void onResume()
     {
         super .onResume();
         // 为系统的加速度传感器注册监听器
         sensorManager.registerListener( this ,
             sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
             SensorManager.SENSOR_DELAY_GAME);
     }
 
     @Override
     protected void onStop()
     {
         // 取消注册
         sensorManager.unregisterListener( this );
         super .onStop();
     }
 
     // 以下是实现SensorEventListener接口必须实现的方法
     // 当传感器的值发生改变时回调该方法
     @Override
     public void onSensorChanged(SensorEvent event)
     {
         float [] values = event.values;
         StringBuilder sb = new StringBuilder();
         sb.append(X方向上的加速度:);
         sb.append(values[ 0 ]);
         sb.append(
Y方向上的加速度:);
         sb.append(values[ 1 ]);
         sb.append(
Z方向上的加速度:);
         sb.append(values[ 2 ]);
         etTxt1.setText(sb.toString());
     }
 
     // 当传感器精度改变时回调该方法。
     @Override
     public void onAccuracyChanged(Sensor sensor, int accuracy)
     {
     }
}

 

需要指出的是,传感器的坐标系统与屏幕坐标系统不同,传感器坐标系统的X轴沿屏幕向右;Y轴则沿屏幕向上,Z轴在垂直屏幕向上。

\

当拿着手机横向左右移动时,可能产生X轴上的加速度;拿着手机前后移动时,可能产生Y轴上的加速度;当拿着手机竖向上下移动时,可能产生Z轴上的加速度。

 

1.2 下载和安装SensorSimulator

SensorSimulator是传感器的模拟工具,安装这个模拟工具之后,开发者就可以在Android模拟器上开发、调试传感器应用。

SensorSimulator,由PC端程序和手机端程序组成,当两端的程序运行并建立连接之后,用户可以通过PC端的程序来改变手机的传感数据。

下载和安装SensorSimulator步骤如下:

登录到http://code.google.com/p/openintents/wiki/SensorSimulator站点或FTP上,下载SensorSimulator的最新版本。

下载SensorSimulator工具后,下载完成后得到一个sensorsimulator-2.0-rc1.zip压缩包。解压该文件,得到如下文件结构。

\

安装SensorSimulator的手机端程序。通过命令窗口进入到上面文件的bin目录下,输入如下命令来安装SensorSimulatorSettings-2.0-rc1.apk文件。adb install SensorSimulatorSettings-2.0-rc1.apk

\

运行SensorSimulator的PC端程序,通过命令窗口进入到上面文件的bin目录下,并在窗口内执行如下命令:java –jar sensorsimulator-2.0-rc1.jar。运行该程序出现如下界面。

运行SensorSimulator的手机端程序。

在SensorSimulator的手机端程序中填写SensorSimulator的PC端程序的监听IP地址、监听端口。

切换到SensorSimulator的Testting Tab页,单击该Tab里的Connect按钮,SensorSimulator手机端和PC端连接。

 

1.3 利用SensorSimulator开发传感器应用

通过使用SensorSimulator,接下来就可以在Android模拟器中开发、调试传感器应用了。不过使用SensorSimulator开发传感器应用与开发真实的传感器应用略有区别。

Android应用必须通过引用外部JAR包的形式来引用SensorSimulator的lib目录下的sensorsimulator-2.0-rc1.jar包。

在应用项目上右键单击选择“Build Path” à “Add External Archives…”,找到sensorsimulator-2.0-rc1.jar所在位置,将其添加到项目中。

应用程序编程使用SensorManagerSimulator代替了原有的SensorManager。

应用程序获取SensorManagerSimulator之后,需要调用connectSimulator()方法连接模拟器。

应用程序编程时所用的Sensor、SensorEvent、 SensorEventListener等不再是Android提供的类,而是由SensorSimulator提供的类。

应用程序需要访问网络的权限。

例:利用传感模拟工具开发加速度传感器:

 

AccelSimulatorTest.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import org.openintents.sensorsimulator.hardware.SensorManagerSimulator;
import org.openintents.sensorsimulator.hardware.Sensor;
import org.openintents.sensorsimulator.hardware.SensorEvent;
import org.openintents.sensorsimulator.hardware.SensorEventListener;
 
import android.app.Activity;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.EditText;
 
public class AccelSimulatorTest extends Activity
     implements SensorEventListener
{
     // 定义模拟器的Sensor管理器
     private SensorManagerSimulator mSensorManager;
     // 定义界面上的文本框组件
     EditText etTxt1;
 
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.main);
         // 获取程序界面的文本框组件
         etTxt1 = (EditText) findViewById(R.id.txt1);
         // 获取传感器模拟器的传感器管理服务
         mSensorManager = SensorManagerSimulator.getSystemService(
             this , SENSOR_SERVICE);
         // 连接传感器模拟器
         mSensorManager.connectSimulator();
     }
 
     @Override
     protected void onResume()
     {
         super .onResume();
         // 为系统的加速度传感器注册监听器
         mSensorManager.registerListener( this ,
             mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
             SensorManager.SENSOR_DELAY_GAME);
     }
 
     @Override
     protected void onStop()
     {
         // 取消注册
         mSensorManager.unregisterListener( this );
         super .onStop();
     }
 
     // 以下是实现SensorEventListener接口必须实现的方法
     // 当传感器的值发生改变时回调该方法
     @Override
     public void onSensorChanged(SensorEvent event)
     {
         float [] values = event.values;
         StringBuilder sb = new StringBuilder();
         sb.append(X方向上的加速度:);
         sb.append(values[ 0 ]);
         sb.append(
Y方向上的加速度:);
         sb.append(values[ 1 ]);
         sb.append(
Z方向上的加速度:);
         sb.append(values[ 2 ]);
         etTxt1.setText(sb.toString());
     }
 
     @Override
     // 当传感器精度改变时回调该方法。
     public void onAccuracyChanged(Sensor sensor, int accuracy)
     {
     }
}

 

?
1
2
<!-- 通过模拟器调试需要访问网络 -->
     <uses-permission android:name= "android.permission.INTERNET/" ></uses-permission>

 

Android的常用传感器

2.1加速度传感器Accelerometer

加速度传感器主要感应手机的运动,在注册了传感器监听器后加速度传感器主要捕获3个参数values[0]、values[1]、values[2]。

values[0]:空间坐标系中x轴方向上的加速度减去重力加速度减去中立加速度在x轴上的分量。

values[1]:空间坐标系中x轴方向上的加速度减去重力加速度减去中立加速度在y轴上的分量。

values[2]:空间坐标系中x轴方向上的加速度减去重力加速度减去中立加速度在z轴上的分量。

上述3个数据的单位均为米每二次方秒。

距离说明:

当手机平放到桌面静止时,加速度为重力加速度g,通过0减去-g(重力加速度g方向为z轴反方向,故为负值)得到values[2]为g。

如果把手机水平方向右推,此时手机x方向上的加速度为正,即values[0]为正。

当把手机以a米每二次方秒的加速度竖值向上举时,values[2]的返回值为(a+g)米每二次方秒,通过a减去-g得到。

 

2.2 方向传感器Orientation

方向传感器主要感应手机方位的变化,其每次读取的都是静态的状态值,在注册了传感器监听器后方向传感器主要捕获3个参数values[0]、values[1]、values[2],关于三个角度的说明如下:

第一个角度:表示手机顶部朝向与正北方向的夹角。当手机绕着Z轴旋转时,该角度值发生改变。

第二个角度:表示手机顶部或尾部翘起的角度,当手机绕着X轴倾斜时,该角度值发生变化。

第三个角度:表示手机左侧或右侧翘起的角度。当手机绕着Y轴倾斜时,该角度值发生变化。

 

2.3磁场传感器Magnetic Field

磁场传感器主要用于感应周围的磁感应强度。即使周围没有任何直接的磁场,手机设备也始终会处于地球磁场中。随着手机状态设备摆放状态的改变,周围磁场在手机的X、Y、Z方向上的会发生改变。

磁场传感器传感器会返回三个数据,三个数据分别代表周围磁场分解到X、Y、Z三个方向上的磁场分量。磁场数据的单位是微特斯拉(uT)。

 

2.4光传感器Light

光传感器用于感应周围的光强,注册监听器后只捕获一个参数:values[0]。该参数代表周围的光照强度,单位为勒克斯(lux)。

 

2.5温度传感器Temperature

温度传感器用于获取手机设备所处环境的温度。温度传感器会返回一个数据,该数据代表手机设备周围的温度,单位是摄氏度。

 

2.6压力传感器 Pressure

压力传感器用于获取手机设备所处环境的压力的大小。压力传感器会返回一个数据,代表手机设备周围的压力大小。

 

例:传感器应用:

\

 

SensorSimulatorTest.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
public class SensorSimulatorTest extends Activity
     implements SensorEventListener
{
     // // 定义真机的Sensor管理器
     // private SensorManager mSensorManager;
     // 定义模拟器的Sensor管理器
     private SensorManagerSimulator mSensorManager;
 
     EditText etOrientation;
     EditText etMagnetic;
     EditText etTemerature;
     EditText etLight;
     EditText etPressure;
 
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.main);
         // 获取界面上的EditText组件
         etOrientation = (EditText) findViewById(R.id.etOrientation);
         etMagnetic = (EditText) findViewById(R.id.etMagnetic);
         etTemerature = (EditText) findViewById(R.id.etTemerature);
         etLight = (EditText) findViewById(R.id.etLight);
         etPressure = (EditText) findViewById(R.id.etPressure);
         // 获取真机的传感器管理服务
         // mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
         // 获取传感器模拟器的传感器管理服务
         mSensorManager = SensorManagerSimulator.getSystemService( this ,
             SENSOR_SERVICE);
         // 连接传感器模拟器
         mSensorManager.connectSimulator();
     }
 
     @Override
     protected void onResume()
     {
         super .onResume();
         // 为系统的方向传感器注册监听器
         mSensorManager.registerListener( this ,
             mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
             SensorManager.SENSOR_DELAY_GAME);
         // 为系统的磁场传感器注册监听器
         mSensorManager.registerListener( this ,
             mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
             SensorManager.SENSOR_DELAY_GAME);
         // 为系统的温度传感器注册监听器
         mSensorManager.registerListener( this ,
             mSensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE),
             SensorManager.SENSOR_DELAY_GAME);
         // 为系统的光传感器注册监听器
         mSensorManager.registerListener( this ,
             mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
             SensorManager.SENSOR_DELAY_GAME);
         // 为系统的压力传感器注册监听器
         mSensorManager.registerListener( this ,
             mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE),
             SensorManager.SENSOR_DELAY_GAME);
     }
 
     @Override
     protected void onStop()
     {
         // 程序退出时取消注册传感器监听器
         mSensorManager.unregisterListener( this );
         super .onStop();
     }
 
     @Override
     protected void onPause()
     {
         // 程序暂停时取消注册传感器监听器
         mSensorManager.unregisterListener( this );
         super .onPause();
     }
 
     // 以下是实现SensorEventListener接口必须实现的方法
     @Override
     // 当传感器精度改变时回调该方法。
     public void onAccuracyChanged(Sensor sensor, int accuracy)
     {
     }
 
     @Override
     public void onSensorChanged(SensorEvent event)
     {
         float [] values = event.values;
         // // 真机上获取触发event的传感器类型
         // int sensorType = event.sensor.getType();
         // 模拟器上获取触发event的传感器类型
         int sensorType = event.type;
         StringBuilder sb = null ;
         // 判断是哪个传感器发生改变
         switch (sensorType)
         {
             // 方向传感器
             case Sensor.TYPE_ORIENTATION:
                 sb = new StringBuilder();
                 sb.append(绕Z轴转过的角度:);
                 sb.append(values[ 0 ]);
                 sb.append(
绕X轴转过的角度:);
                 sb.append(values[ 1 ]);
                 sb.append(
绕Y轴转过的角度:);
                 sb.append(values[ 2 ]);
                 etOrientation.setText(sb.toString());
                 break ;
             // 磁场传感器
             case Sensor.TYPE_MAGNETIC_FIELD:
                 sb = new StringBuilder();
                 sb.append(X方向上的角度:);
                 sb.append(values[ 0 ]);
                 sb.append(
Y方向上的角度:);
                 sb.append(values[ 1 ]);
                 sb.append(
Z方向上的角度:);
                 sb.append(values[ 2 ]);
                 etMagnetic.setText(sb.toString());
                 break ;
             // 温度传感器
             case Sensor.TYPE_TEMPERATURE:
                 sb = new StringBuilder();
                 sb.append(当前温度为:);
                 sb.append(values[ 0 ]);
                 etTemerature.setText(sb.toString());
                 break ;
             // 光传感器
             case Sensor.TYPE_LIGHT:
                 sb = new StringBuilder();
                 sb.append(当前光的强度为:);
                 sb.append(values[ 0 ]);
                 etLight.setText(sb.toString());
                 break ;
             // 压力传感器
             case Sensor.TYPE_PRESSURE:
                 sb = new StringBuilder();
                 sb.append(当前压力为:);
                 sb.append(values[ 0 ]);
                 etPressure.setText(sb.toString());
                 break ;
         }
     }
}

 

传感器应用案例

对传感器的支持是Android系统的特性之一,通过使用传感器可以开发出各种有趣的应用,我们通过方向传感器来开发指南针。

开发指南针的思路比较简单:程序先准备一张指南针图片,该图片上方向指针指向北方。接下来开发一个检测方向的传感器,程序检测到手机顶部绕Z轴转过多少度,让指南针图片反向转过多少度即可。

该应用中只要在界面中添加一张图片,并让图片总是反向转过方向传感器反回的第一个角度即可。

 

例:指南针:

\

Compass.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public class Compass extends Activity
     implements SensorEventListener
{
     // 定义显示指南针的图片
     ImageView znzImage;
     // 记录指南针图片转过的角度
     float currentDegree = 0f;
     // 定义模拟器的Sensor管理器
//  private SensorManagerSimulator mSensorManager;
 
      // 定义真机的Sensor管理器
     SensorManager mSensorManager;
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.main);
         // 获取界面中显示指南针的图片
         znzImage = (ImageView) findViewById(R.id.znzImage);
 
          // 获取真机的传感器管理服务
          mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
//      // 获取传感器模拟器的传感器管理服务
//      mSensorManager = SensorManagerSimulator.getSystemService(this,
//          SENSOR_SERVICE);
//      // 连接传感器模拟器
//      mSensorManager.connectSimulator();
     }
 
     @Override
     protected 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 onSensorChanged(SensorEvent event)
     {
         // 真机上获取触发event的传感器类型
         int sensorType = event.sensor.getType();
//      // 模拟器上获取触发event的传感器类型
//      int sensorType = event.type;
         switch (sensorType)
         {
             case Sensor.TYPE_ORIENTATION:
                 // 获取绕Z轴转过的角度。
                 float degree = event.values[ 0 ];
                 // 创建旋转动画(反向转过degree度)
                 RotateAnimation ra = new RotateAnimation(currentDegree,
                     -degree, Animation.RELATIVE_TO_SELF, 0 .5f,
                     Animation.RELATIVE_TO_SELF, 0 .5f);
                 // 设置动画的持续时间
                 ra.setDuration( 200 );
                 // 运行动画
                 znzImage.startAnimation(ra);
                 currentDegree = -degree;
                 break ;
         }
     }
 
     @Override
     public void onAccuracyChanged(Sensor sensor, int accuracy)
     {
     }
}

 

main.xml

?
1
2
3
4
<!--?xml version= 1.0 encoding=utf- 8 ?-->
<linearlayout android:background= "#fff" android:layout_height= "fill_parent" android:layout_width= "fill_parent" android:orientation= "vertical" xmlns:android= "http://schemas.android.com/apk/res/android" >
<imageview android:id= "@+id/znzImage" android:layout_height= "fill_parent" android:layout_width= "fill_parent" android:scaletype= "fitCenter" android:src= "@drawable/znz" >
</imageview></linearlayout>

 

例:水平仪:

Gradienter.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
public class Gradienter extends Activity implements SensorEventListener
{
     // 定义水平仪的仪表盘
     MyView show;
     // 定义水平仪能处理的最大倾斜角,超过该角度,气泡将直接在位于边界。
     int MAX_ANGLE = 30 ;
     // // 定义真机的Sensor管理器
     // SensorManager mSensorManager;
     // 定义模拟器的Sensor管理器
     SensorManagerSimulator 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);
         // 获取传感器模拟器的传感器管理服务
         mSensorManager = SensorManagerSimulator.getSystemService( this ,
             SENSOR_SERVICE);
         // 连接传感器模拟器
         mSensorManager.connectSimulator();
     }
 
     @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();
         // 模拟器上获取触发event的传感器类型
         int sensorType = event.type;
         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 ;
         }
     }
}

 

MyView.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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 );
     }
}

 

 

?
1
2
3
4
<!--?xml version= 1.0 encoding=utf- 8 ?-->
<framelayout android:background= "#fff" android:layout_height= "fill_parent" android:layout_width= "fill_parent" android:orientation= "vertical" xmlns:android= "http://schemas.android.com/apk/res/android" >
<com.boby.sensor.myview android:id= "@+id/show" android:layout_height= "fill_parent" android:layout_width= "fill_parent" >
</com.boby.sensor.myview></framelayout>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值