加速傳感器
public class MainActivity extends AppCompatActivity implements SensorEventListener {
// 定義系統(tǒng)的Sensor管理器
private SensorManager sensorManager;
private TextView etTxt1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 獲取程序界面上的文本框組件
etTxt1 = findViewById(R.id.txt1);
// 獲取系統(tǒng)的傳感器管理服務(wù)
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); // ①
}
@Override
public void onResume() {
super.onResume();
/*
* 為系統(tǒng)的加速度傳感器注冊監(jiān)聽器
*
* SENSOR_DELAY_FASTEST 最快。延遲最小,只有特別依賴于傳感器數(shù)據(jù)的應(yīng)用推薦采用這種頻率,該種模式可能造成手機(jī)電量大量消耗暖释。由于傳遞的為原始數(shù)據(jù)垢啼,算法處理不好將會影響應(yīng)用的性能阿逃。
* SENSOR_DELAY_GAME 適合游戲的頻率先慷。一般有實(shí)時(shí)性要求的應(yīng)用適合使用這種頻率
* SENSOR_DELAY_NORMAL 正常頻率。一般對實(shí)時(shí)性要求不是特別高的應(yīng)用適合使用這種頻率蹄梢。
* SENSOR_DELAY_UI 適合普通用戶界面的頻率。這種模式比較省電富俄,而且系統(tǒng)開銷也很小禁炒,但延遲較大而咆,因此只適合在普通小程序中使用。
* */
sensorManager.registerListener(this, sensorManager.getDefaultSensor(
Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI); // ②
}
@Override
public void onPause() {
super.onPause();
// 取消注冊
sensorManager.unregisterListener(this);
}
// 以下是實(shí)現(xiàn)SensorEventListener接口必須實(shí)現(xiàn)的方法
// 當(dāng)傳感器的值發(fā)生改變時(shí)回調(diào)該方法
@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
String sb = "X方向上的加速度:" +
values[0] +
"\nY方向上的加速度:" +
values[1] +
"\nZ方向上的加速度:" +
values[2];
etTxt1.setText(sb);
}
// 當(dāng)傳感器精度改變時(shí)回調(diào)該方法
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
常用傳感器
public class MainActivity extends AppCompatActivity implements SensorEventListener {
// 定義Sensor管理器
private SensorManager mSensorManager;
private TextView etOrientation;
private TextView etGyro;
private TextView etMagnetic;
private TextView etGravity;
private TextView etLinearAcc;
private TextView etTemerature;
private TextView etHumidity;
private TextView etLight;
private TextView etPressure;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 獲取界面上的TextView組件
etOrientation = findViewById(R.id.etOrientation);
etGyro = findViewById(R.id.etGyro);
etMagnetic = findViewById(R.id.etMagnetic);
etGravity = findViewById(R.id.etGravity);
etLinearAcc = findViewById(R.id.etLinearAcc);
etTemerature = findViewById(R.id.etTemerature);
etHumidity = findViewById(R.id.etHumidity);
etLight = findViewById(R.id.etLight);
etPressure = findViewById(R.id.etPressure);
// 獲取傳感器管理服務(wù)
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); // ①
}
@Override
public void onResume() {
super.onResume();
// 為系統(tǒng)的方向傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_GAME);
// 為系統(tǒng)的陀螺儀傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
SensorManager.SENSOR_DELAY_GAME);
// 為系統(tǒng)的磁場傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_GAME);
// 為系統(tǒng)的重力傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY),
SensorManager.SENSOR_DELAY_GAME);
// 為系統(tǒng)的線性加速度傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION),
SensorManager.SENSOR_DELAY_GAME);
// 為系統(tǒng)的溫度傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE),
SensorManager.SENSOR_DELAY_GAME);
// 為系統(tǒng)的濕度傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_RELATIVE_HUMIDITY),
SensorManager.SENSOR_DELAY_GAME);
// 為系統(tǒng)的光傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
SensorManager.SENSOR_DELAY_GAME);
// 為系統(tǒng)的壓力傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE),
SensorManager.SENSOR_DELAY_GAME);
}
@Override
public void onPause() {
// 程序暫停時(shí)取消注冊傳感器監(jiān)聽器
mSensorManager.unregisterListener(this);
super.onPause();
}
// 以下是實(shí)現(xiàn)SensorEventListener接口必須實(shí)現(xiàn)的方法
// 當(dāng)傳感器精度改變時(shí)回調(diào)該方法
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
// 獲取觸發(fā)event的傳感器類型
int sensorType = event.sensor.getType();
StringBuilder sb;
// 判斷是哪個(gè)傳感器發(fā)生改變
switch (sensorType) {
// 方向傳感器
case Sensor.TYPE_ORIENTATION:
sb = new StringBuilder();
sb.append("繞Z軸轉(zhuǎn)過的角度:");
sb.append(values[0]);
sb.append("\n繞X軸轉(zhuǎn)過的角度:");
sb.append(values[1]);
sb.append("\n繞Y軸轉(zhuǎn)過的角度:");
sb.append(values[2]);
etOrientation.setText(sb.toString());
break;
// 陀螺儀傳感器
case Sensor.TYPE_GYROSCOPE:
sb = new StringBuilder();
sb.append("繞X軸旋轉(zhuǎn)的角速度:");
sb.append(values[0]);
sb.append("\n繞Y軸旋轉(zhuǎn)的角速度:");
sb.append(values[1]);
sb.append("\n繞Z軸旋轉(zhuǎn)的角速度:");
sb.append(values[2]);
etGyro.setText(sb.toString());
break;
// 磁場傳感器
case Sensor.TYPE_MAGNETIC_FIELD:
sb = new StringBuilder();
sb.append("X軸方向上的磁場強(qiáng)度:");
sb.append(values[0]);
sb.append("\nY軸方向上的磁場強(qiáng)度:");
sb.append(values[1]);
sb.append("\nZ軸方向上的磁場強(qiáng)度:");
sb.append(values[2]);
etMagnetic.setText(sb.toString());
break;
// 重力傳感器
case Sensor.TYPE_GRAVITY:
sb = new StringBuilder();
sb.append("X軸方向上的重力:");
sb.append(values[0]);
sb.append("\nY軸方向上的重力:");
sb.append(values[1]);
sb.append("\nZ軸方向上的重力:");
sb.append(values[2]);
etGravity.setText(sb.toString());
break;
// 線性加速度傳感器
case Sensor.TYPE_LINEAR_ACCELERATION:
sb = new StringBuilder();
sb.append("X軸方向上的線性加速度:");
sb.append(values[0]);
sb.append("\nY軸方向上的線性加速度:");
sb.append(values[1]);
sb.append("\nZ軸方向上的線性加速度:");
sb.append(values[2]);
etLinearAcc.setText(sb.toString());
break;
// 溫度傳感器
case Sensor.TYPE_AMBIENT_TEMPERATURE:
sb = new StringBuilder();
sb.append("當(dāng)前溫度為:");
sb.append(values[0]);
etTemerature.setText(sb.toString());
break;
// 濕度傳感器
case Sensor.TYPE_RELATIVE_HUMIDITY:
sb = new StringBuilder();
sb.append("當(dāng)前濕度為:");
sb.append(values[0]);
etHumidity.setText(sb.toString());
break;
// 光傳感器
case Sensor.TYPE_LIGHT:
sb = new StringBuilder();
sb.append("當(dāng)前光的強(qiáng)度為:");
sb.append(values[0]);
etLight.setText(sb.toString());
break;
// 壓力傳感器
case Sensor.TYPE_PRESSURE:
sb = new StringBuilder();
sb.append("當(dāng)前壓力為:");
sb.append(values[0]);
etPressure.setText(sb.toString());
break;
}
}
}
實(shí)例:指南針
public class MainActivity extends AppCompatActivity implements SensorEventListener {
// 定義顯示指南針的圖片
private ImageView znzIV;
// 記錄指南針圖片轉(zhuǎn)過的角度
private float currentDegree = 0f;
// 定義Sensor管理器
private SensorManager mSensorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
znzIV = findViewById(R.id.znzImage);
// 獲取傳感器管理服務(wù)
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}
@Override
public void onResume() {
super.onResume();
// 為系統(tǒng)的方向傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_GAME);
}
@Override
public void onPause() {
// 取消注冊
mSensorManager.unregisterListener(this);
super.onPause();
}
@Override
public void onSensorChanged(SensorEvent event) {
// 獲取觸發(fā)event的傳感器類型
int sensorType = event.sensor.getType();
switch (sensorType) {
case Sensor.TYPE_ORIENTATION:
// 獲取繞Z軸轉(zhuǎn)過的角度
float degree = event.values[0];
// 創(chuàng)建旋轉(zhuǎn)動畫(反向轉(zhuǎn)過degree度)
RotateAnimation ra = new RotateAnimation(currentDegree, -degree,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
// 設(shè)置動畫的持續(xù)時(shí)間
ra.setDuration(200);
// 運(yùn)行動畫
znzIV.startAnimation(ra);
currentDegree = -degree;
break;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
實(shí)例:水平儀
MyView
public class MyView extends View {
// 定義水平儀儀表盤圖片
Bitmap back;
// 定義水平儀中的氣泡圖標(biāo)
Bitmap bubble;
// 定義水平儀中氣泡的X幕袱、Y坐標(biāo)
float bubbleX = 0f;
float bubbleY = 0f;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// 獲取窗口管理器
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
// 獲取屏幕的寬度和高度
Display display = wm.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
int screenWidth = metrics.widthPixels;
// 創(chuàng)建位圖
back = Bitmap.createBitmap(screenWidth, screenWidth,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(back);
Paint paint = new Paint();
paint.setAntiAlias(true);
// 設(shè)置繪制風(fēng)格:僅填充
paint.setStyle(Paint.Style.FILL);
// 創(chuàng)建一個(gè)線性漸變來繪制線性漸變
LinearGradient shader = new LinearGradient(0f, screenWidth, screenWidth * 0.8f,
screenWidth * 0.2f, Color.YELLOW, Color.WHITE, Shader.TileMode.MIRROR);
paint.setShader(shader);
// 繪制圓形
canvas.drawCircle(screenWidth / 2, screenWidth / 2, screenWidth / 2, paint);
Paint paint2 = new Paint();
paint2.setAntiAlias(true);
// 設(shè)置繪制風(fēng)格:僅繪制邊框
paint2.setStyle(Paint.Style.STROKE);
paint2.setStrokeWidth(5f); // 設(shè)置畫筆寬度
paint2.setColor(Color.BLACK); // 設(shè)置畫筆顏色
// 繪制圓形邊框
canvas.drawCircle(screenWidth / 2, screenWidth / 2, screenWidth / 2, paint2);
// 繪制水平橫線
canvas.drawLine(0f, screenWidth / 2, screenWidth, screenWidth / 2, paint2);
// 繪制垂直橫線
canvas.drawLine(screenWidth / 2, 0f, screenWidth / 2, screenWidth, paint2);
paint2.setStrokeWidth(10f); // 設(shè)置畫筆寬度
// 設(shè)置畫筆顏色
paint2.setColor(Color.RED);
// 繪制中心的紅色“十”字
canvas.drawLine(screenWidth / 2 - 30, screenWidth / 2,
screenWidth / 2 + 30, screenWidth / 2, paint2);
canvas.drawLine(screenWidth / 2, screenWidth / 2 - 30,
screenWidth / 2, screenWidth / 2 + 30, paint2);
// 加載氣泡圖片
bubble = BitmapFactory.decodeResource(getResources(), R.drawable.bubble);
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 繪制水平儀儀表盤圖片
canvas.drawBitmap(back, 0f, 0f, null);
// 根據(jù)氣泡坐標(biāo)繪制氣泡
canvas.drawBitmap(bubble, bubbleX, bubbleY, null);
}
}
public class MainActivity extends AppCompatActivity implements SensorEventListener {
public final static int MAX_ANGLE = 30;
// 定義水平儀的儀表盤
private MyView show;
// 定義Sensor管理器
private SensorManager mSensorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 獲取水平儀的主組件
show = findViewById(R.id.show);
// 獲取傳感器管理服務(wù)
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}
@Override
public void onResume() {
super.onResume();
// 為系統(tǒng)的方向傳感器注冊監(jiān)聽器
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_GAME);
}
@Override
public void onPause() {
// 取消注冊
mSensorManager.unregisterListener(this);
super.onPause();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
// 獲取觸發(fā)event的傳感器類型
int sensorType = event.sensor.getType();
switch (sensorType) {
case Sensor.TYPE_ORIENTATION:
// 獲取與Y軸的夾角
float yAngle = values[1];
// 獲取與Z軸的夾角
float zAngle = values[2];
// 氣泡位于中間時(shí)(水平儀完全水平)暴备,氣泡的X、Y坐標(biāo)
float x = (show.back.getWidth() - show.bubble.getWidth()) / 2;
float y = (show.back.getHeight() - show.bubble.getHeight()) / 2;
// 如果與Z軸的傾斜角還在最大角度之內(nèi)
if (Math.abs(zAngle) <= MAX_ANGLE) {
// 根據(jù)與Z軸的傾斜角度計(jì)算X坐標(biāo)的變化值
// (傾斜角度越大们豌,X坐標(biāo)變化越大)
int deltaX = (int) ((show.back.getWidth() - show.bubble
.getWidth()) / 2 * zAngle / MAX_ANGLE);
x += deltaX;
}
// 如果與Z軸的傾斜角已經(jīng)大于MAX_ANGLE涯捻,氣泡應(yīng)到最左邊
else if (zAngle > MAX_ANGLE) {
x = 0;
}
// 如果與Z軸的傾斜角已經(jīng)小于負(fù)的MAX_ANGLE,氣泡應(yīng)到最右邊
else {
x = show.back.getWidth() - show.bubble.getWidth();
}
// 如果與Y軸的傾斜角還在最大角度之內(nèi)
if (Math.abs(yAngle) <= MAX_ANGLE) {
// 根據(jù)與Y軸的傾斜角度計(jì)算Y坐標(biāo)的變化值
// (傾斜角度越大玛痊,Y坐標(biāo)變化越大)
int deltaY = (int) ((show.back.getHeight() - show.bubble
.getHeight()) / 2 * yAngle / MAX_ANGLE);
y += deltaY;
}
// 如果與Y軸的傾斜角已經(jīng)大于MAX_ANGLE汰瘫,氣泡應(yīng)到最下邊
else if (yAngle > MAX_ANGLE) {
y = show.back.getHeight() - show.bubble.getHeight();
}
// 如果與Y軸的傾斜角已經(jīng)小于負(fù)的MAX_ANGLE,氣泡應(yīng)到最上邊
else {
y = 0;
}
// 如果計(jì)算出來的X擂煞、Y坐標(biāo)還位于水平儀的儀表盤內(nèi)混弥,更新水平儀的氣泡坐標(biāo)
if (isContain(x, y)) {
show.bubbleX = x;
show.bubbleY = y;
}
// 通知系統(tǒng)重繪MyView組件
show.postInvalidate();
break;
}
}
// 計(jì)算x、y點(diǎn)的氣泡是否處于水平儀的儀表盤內(nèi)
private boolean isContain(float x, float y) {
// 計(jì)算氣泡的圓心坐標(biāo)X对省、Y
float bubbleCx = x + show.bubble.getWidth() / 2;
float bubbleCy = y + show.bubble.getHeight() / 2;
// 計(jì)算水平儀儀表盤的圓心坐標(biāo)X蝗拿、Y
float backCx = show.back.getWidth() / 2;
float backCy = show.back.getHeight() / 2;
// 計(jì)算氣泡的圓心與水平儀儀表盤的圓心之間的距離
double distance = Math.sqrt((bubbleCx - backCx) * (bubbleCx - backCx) +
(bubbleCy - backCy) * (bubbleCy - backCy));
// 若兩個(gè)圓心的距離小于它們的半徑差,即可認(rèn)為處于該點(diǎn)的氣泡依然位于儀表盤內(nèi)
return distance < (show.back.getWidth() - show.bubble.getWidth()) / 2;
}
}
摘抄至《瘋狂Android講義(第4版)》