0922Android传感器实例指南针
指指指指南針
實(shí)現(xiàn)指南針能夠旋轉(zhuǎn)要求手機(jī)內(nèi)部有地磁傳感器和加速度傳感器,然后用自定義View畫出指南針。通過地磁傳感器計(jì)算出的角度,通過一系列的計(jì)算將這個(gè)角度轉(zhuǎn)換成合適的角度后利用自定義View中的角度的set方法來將角度傳到自定義View中。在surface中開啟一個(gè)線程實(shí)現(xiàn)指南針的動(dòng)畫。
傳感器部分
Android中的傳感器的用法其實(shí)都很類似。首先第一步要獲取到SensorManager的實(shí)例
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);SensorManager是系統(tǒng)所有傳感器的管理器,調(diào)用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); 此時(shí)的magneticSensor 就代表著一個(gè)地磁傳感器,accelerometerSensor 代表著一個(gè)加速度傳感器。
接下來對(duì)傳感器輸出的信號(hào)進(jìn)行監(jiān)聽,借助SensorEventListener來實(shí)現(xiàn)。SensorEventListener是一個(gè)接口,其中定義了onSensorChanged()和onAccuaryChanged()這兩個(gè)方法,仔細(xì)看注釋。
下面需要調(diào)用SensorManager的registerListener來注冊(cè)才能生效,傳入三個(gè)參數(shù),第一個(gè)是SensorEventListener的實(shí)例,第二個(gè)是Sensor的實(shí)例,第三個(gè)參數(shù)是傳感器輸出信息的跟新速率。
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部分,就是自己畫個(gè)指南針,然后指定“動(dòng)”的部分然后放到線程里旋轉(zhuǎn)畫布就搞定了╮(╯▽╰)╭。
這里涉及到SurfaceView,SurfaceView一般會(huì)與SurfaceHolder結(jié)合使用,SurfaceHolder用于向與之關(guān)聯(lián)的SurfaceView上繪圖,調(diào)用SurfaceView的getHolder方法即可獲取SurfaceView關(guān)聯(lián)的SurfaceHolder
SurfaceHolder提供了如下方法來獲取Canvas對(duì)象
- Canvas lockCanvas():鎖定整個(gè)SurfaceView對(duì)象,獲取該Surface上的Canvas。
- Canvas lockCanvas(Rect dirty):鎖定SurfaceView上Rect劃分的區(qū)域,獲取該Surface上的Canvas
當(dāng)通過lockCanvas()獲取指定了SurfaceView上的Canvas后,接下來程序就可以調(diào)用Canvas進(jìn)行繪圖了,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();//保存當(dāng)前狀態(tài)canvas.rotate(degree, width / 2, heigth / 2);//繞中心點(diǎn)旋轉(zhuǎn),實(shí)現(xiàn)指針旋轉(zhuǎn)部分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;}}上面的程序還添加了一個(gè)CallBack實(shí)例,其中定義了如下三個(gè)方法
- void surfaceCreated(SurfaceHolder holder):當(dāng)surface被創(chuàng)建時(shí)回調(diào)該方法
- void surfaceChanged(SurfaceHolder holder, int format, int width, int height):當(dāng)一個(gè)surface格式或大小發(fā)生改變時(shí)回調(diào)該方法。
- void surfaceDestroyed(SurfaceHolder holder):當(dāng)surface將要銷毀時(shí)回調(diào)該方法。
控制指南針動(dòng)的部分
canvas.save();//保存當(dāng)前狀態(tài)canvas.rotate(degree, width / 2, heigth / 2);//繞中心點(diǎn)旋轉(zhuǎn),實(shí)現(xiàn)指針旋轉(zhuǎn)部分canvas.drawLine(width / 2, heigth / 2 - 204, width / 2, heigth / 2 - 240, mPaintNorth);canvas.drawCircle(width / 2, heigth / 2, 222, mPaint);canvas.restore();活動(dòng)中的全部代碼
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) { // 判斷當(dāng)前是加速度傳感器還是地磁傳感器if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { // 注意賦值時(shí)要調(diào)用clone()方法,不然accelerometerValues和magneticValues將會(huì)指向同一個(gè)引用。accelerometerValues = event.values.clone();} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { // 注意賦值時(shí)要調(diào)用clone()方法,不然accelerometerValues和magneticValues將會(huì)指向同一個(gè)引用。magneticValues = event.values.clone();}float[] R = new float[9];float[] values = new float[3]; // 得到一個(gè)包含旋轉(zhuǎn)矩陣的R數(shù)組,第一個(gè)參數(shù)R是一個(gè)長度為9的float數(shù)組,這個(gè)方法計(jì)算出的旋轉(zhuǎn)數(shù)據(jù)就會(huì)賦值到這個(gè)數(shù)組中 // ,第二個(gè)參數(shù)是一個(gè)用于將地磁向量轉(zhuǎn)換成重力坐標(biāo)的旋轉(zhuǎn)矩陣,通常指定為null即可。 // 第三個(gè)參數(shù)和第四個(gè)參數(shù)分別就是加速度傳感器和地磁傳感器輸出的values值。SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues); // 計(jì)算手機(jī)的旋轉(zhuǎn)數(shù)據(jù) // values是一個(gè)長度為3的float數(shù)組,手機(jī)在各個(gè)方向上的旋轉(zhuǎn)數(shù)據(jù)將會(huì)存放到這個(gè)數(shù)組當(dāng)中 // ,其中values[0]記錄著手機(jī)圍繞Z軸的旋轉(zhuǎn)角度,value[1]和values[2]分別對(duì)應(yīng)X軸和Y軸,這些數(shù)據(jù)都以弧度為單位, // 需要用Math.toDegrees(values[0])轉(zhuǎn)換成角度。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);} }總結(jié)
以上是生活随笔為你收集整理的0922Android传感器实例指南针的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java】java格式化时间到毫秒
- 下一篇: qq群排名霸屏技巧排名推广