0922Android传感器实例指南针
指指指指南針
實現指南針能夠旋轉要求手機內部有地磁傳感器和加速度傳感器,然后用自定義View畫出指南針。通過地磁傳感器計算出的角度,通過一系列的計算將這個角度轉換成合適的角度后利用自定義View中的角度的set方法來將角度傳到自定義View中。在surface中開啟一個線程實現指南針的動畫。
傳感器部分
Android中的傳感器的用法其實都很類似。首先第一步要獲取到SensorManager的實例
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);SensorManager是系統所有傳感器的管理器,調用getDefaultSensor()方法來得到任意的傳感器類型。
Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);Log.d("data", "magneticSensor的值:" + magneticSensor);Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);Log.d("data", "accelerometerSensor的值 : " + accelerometerSensor); 此時的magneticSensor 就代表著一個地磁傳感器,accelerometerSensor 代表著一個加速度傳感器。
接下來對傳感器輸出的信號進行監聽,借助SensorEventListener來實現。SensorEventListener是一個接口,其中定義了onSensorChanged()和onAccuaryChanged()這兩個方法,仔細看注釋。
下面需要調用SensorManager的registerListener來注冊才能生效,傳入三個參數,第一個是SensorEventListener的實例,第二個是Sensor的實例,第三個參數是傳感器輸出信息的跟新速率。
sensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_GAME);sensorManager.registerListener(listener, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);最后在onDestory中銷毀傳感器即可
@Overrideprotected void onDestroy() {super.onDestroy();sensorManager.unregisterListener(listener);}這樣傳感器部分就完成了。
自己畫指南針
接下來是自定義View部分,就是自己畫個指南針,然后指定“動”的部分然后放到線程里旋轉畫布就搞定了╮(╯▽╰)╭。
這里涉及到SurfaceView,SurfaceView一般會與SurfaceHolder結合使用,SurfaceHolder用于向與之關聯的SurfaceView上繪圖,調用SurfaceView的getHolder方法即可獲取SurfaceView關聯的SurfaceHolder
SurfaceHolder提供了如下方法來獲取Canvas對象
- Canvas lockCanvas():鎖定整個SurfaceView對象,獲取該Surface上的Canvas。
- Canvas lockCanvas(Rect dirty):鎖定SurfaceView上Rect劃分的區域,獲取該Surface上的Canvas
當通過lockCanvas()獲取指定了SurfaceView上的Canvas后,接下來程序就可以調用Canvas進行繪圖了,Canvas繪圖完成后通過unlockCanvasAndPost()來釋放繪圖,提交所畫的圖形
public class MyView extends SurfaceView implements SurfaceHolder.Callback {private SurfaceHolder surfaceHolder;private Paint mPaint;private Paint mPaintNorth;private int heigth;private int width;private Thread mThread;private float degree;private boolean flag=true;public void setDegree(float degree) {this.degree = degree;}public MyView(Context context) {super(context);surfaceHolder = getHolder();surfaceHolder.addCallback(this);}public MyView(Context context, AttributeSet attrs) {super(context, attrs);surfaceHolder = getHolder();surfaceHolder.addCallback(this);mPaint = new Paint();mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(5);mPaint.setAntiAlias(true);mPaint.setColor(Color.BLACK);mPaintNorth = new Paint();mPaintNorth.setColor(Color.RED);mPaintNorth.setStrokeWidth(10);mPaintNorth.setAntiAlias(true);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);heigth = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);setMeasuredDimension(width, heigth);}private Canvas canvas;@Overridepublic void surfaceCreated(SurfaceHolder holder) {mThread = new Thread(new Runnable() {@Overridepublic void run() {while (flag) {canvas = surfaceHolder.lockCanvas();Log.d("data", "canvas值: "+canvas);canvas.drawColor(Color.LTGRAY);canvas.drawLine(width / 2, heigth / 2 - 270, width / 2, heigth / 2 + 270, mPaint);canvas.drawLine(width / 2 - 270, heigth / 2, width / 2 + 270, heigth / 2, mPaint);canvas.save();//保存當前狀態canvas.rotate(degree, width / 2, heigth / 2);//繞中心點旋轉,實現指針旋轉部分canvas.drawLine(width / 2, heigth / 2 - 204, width / 2, heigth / 2 - 240, mPaintNorth);canvas.drawCircle(width / 2, heigth / 2, 222, mPaint);canvas.restore();surfaceHolder.unlockCanvasAndPost(canvas);try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}});mThread.start();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {flag=false;}}上面的程序還添加了一個CallBack實例,其中定義了如下三個方法
- void surfaceCreated(SurfaceHolder holder):當surface被創建時回調該方法
- void surfaceChanged(SurfaceHolder holder, int format, int width, int height):當一個surface格式或大小發生改變時回調該方法。
- void surfaceDestroyed(SurfaceHolder holder):當surface將要銷毀時回調該方法。
控制指南針動的部分
canvas.save();//保存當前狀態canvas.rotate(degree, width / 2, heigth / 2);//繞中心點旋轉,實現指針旋轉部分canvas.drawLine(width / 2, heigth / 2 - 204, width / 2, heigth / 2 - 240, mPaintNorth);canvas.drawCircle(width / 2, heigth / 2, 222, mPaint);canvas.restore();活動中的全部代碼
package com.example.laowang.mycompas;import android.app.Activity; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.util.Log;public class MainActivity extends Activity {private SensorManager sensorManager;private MyView myView;private float degree;private SensorEventListener listener = new SensorEventListener() {float[] accelerometerValues = new float[3];float[] magneticValues = new float[3];@Overridepublic void onSensorChanged(SensorEvent event) { // 判斷當前是加速度傳感器還是地磁傳感器if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { // 注意賦值時要調用clone()方法,不然accelerometerValues和magneticValues將會指向同一個引用。accelerometerValues = event.values.clone();} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { // 注意賦值時要調用clone()方法,不然accelerometerValues和magneticValues將會指向同一個引用。magneticValues = event.values.clone();}float[] R = new float[9];float[] values = new float[3]; // 得到一個包含旋轉矩陣的R數組,第一個參數R是一個長度為9的float數組,這個方法計算出的旋轉數據就會賦值到這個數組中 // ,第二個參數是一個用于將地磁向量轉換成重力坐標的旋轉矩陣,通常指定為null即可。 // 第三個參數和第四個參數分別就是加速度傳感器和地磁傳感器輸出的values值。SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues); // 計算手機的旋轉數據 // values是一個長度為3的float數組,手機在各個方向上的旋轉數據將會存放到這個數組當中 // ,其中values[0]記錄著手機圍繞Z軸的旋轉角度,value[1]和values[2]分別對應X軸和Y軸,這些數據都以弧度為單位, // 需要用Math.toDegrees(values[0])轉換成角度。SensorManager.getOrientation(R, values);degree = (float) -Math.toDegrees(values[0]);myView.setDegree(degree);}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);myView = (MyView) findViewById(R.id.my_compass_view);sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);Log.d("data", "magneticSensor的值:" + magneticSensor);Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);Log.d("data", "accelerometerSensor的值 : " + accelerometerSensor);sensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_GAME);sensorManager.registerListener(listener, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);}@Overrideprotected void onDestroy() {super.onDestroy();sensorManager.unregisterListener(listener);} }總結
以上是生活随笔為你收集整理的0922Android传感器实例指南针的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java】java格式化时间到毫秒
- 下一篇: Android打开WIFI、关闭WIFI