简易指南针

Android中的方向传感器在生活中是一个很好的应用,典型的例子是指南针的使用,我们先来简单介绍一下传感器中三个参数x,y,z的含义,以一幅图来说明。

这里写图片描述

                        图 1 

补充说明:图中的坐标轴x,y,z和传感器中的X,Y,Z没有任何联系!
如上图所示,绿色部分表示一个手机,带有小圈那一头是手机头部
传感器中的X:如上图所示,规定X正半轴为北,手机头部指向OF方向,此时X的值为0,如果手机头部指向OG方向,此时X值为90,指向OH方向,X值为180,指向OE,X值为270

传感器中的Y:现在我们将手机沿着BC轴慢慢向上抬起,即手机头部不动,尾部慢慢向上翘起来,直到AD跑到BC右边并落在XOY平面上,Y的值将从0~180之间变动,如果手机沿着AD轴慢慢向上抬起,即手机尾部不懂,直到BC跑到AD左边并且落在XOY平面上,Y的值将从0~-180之间变动,这就是方向传感器中Y的含义。

传感器中的Z:现在我们将手机沿着AB轴慢慢向上抬起,即手机左边框不动,右边框慢慢向上翘起来,直到CD跑到AB右边并落在XOY平面上,Z的值将从0~180之间变动,如果手机沿着CD轴慢慢向上抬起,即手机右边框不动,直到AB跑到CD左边并且落在XOY平面上,Z的值将从0~-180之间变动,这就是方向传感器中发Z的含义。

了解了方向传感器中X,Y,Z的含义之后下面我们就开始学习如何使用
首先我们创建一个传感器管理器和一个传感器监听器,管理器用来管理传感器以及创建各种各样的传感器,监听器用来监视传感器的变化并且进行相应的操作
private SensorManager sensorManager;
private MySensorEventListener mySensorEventListener;
mySensorEventListener= new MySensorEventListener();//这个监听器当然是我们自己定义的,在方向感应器感应到手机方向有变化的时候,我们可以采取相应的操作,这里紧紧是将x,y,z的值打印出来

private final class MySensorEventListener implements  SensorEventListener{

@Override
//可以得到传感器实时测量出来的变化值
public void onSensorChanged(SensorEvent event) {
//方向传感器
if(event.sensor.getType()==Sensor.TYPE_ORIENTATION){
//x表示手机指向的方位,0表示北,90表示东,180表示南,270表示西
float x = event.values[SensorManager.DATA_X];
float y = event.values[SensorManager.DATA_Y];
float z = event.values[SensorManager.DATA_Z];
//tv_orientation是界面上的一个TextView标签,不再赘述
tv_orientation.setText("Orientation:"+x+","+y+","+z);
}
}

我们在onResume方法中创建一个方向传感器,并向系统注册监听器
protected void onResume() {
    Sensor sensor_orientation=sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
    sensorManager.registerListener(mySensorEventListener,sensor_orientation, SensorManager.SENSOR_DELAY_UI);
super.onResume();
}
最后我们在onPause()中注销所有传感器的监听,释放方向感应器资源!
protected void onPause() {
//注销所有传感器的监听
sensorManager.unregisterListener(mySensorEventListener);
super.onPause();
}

下面制作一个简单的指南针:

1、写一个MyView类继承SurfaceView

public class MyView extends SurfaceView implements SurfaceHolder.Callback{
//继承SurfaceView 插入构造器
    private int width;
    private int height;
    private Paint mPaintCircle;
    private Paint mPaintText;
    private Paint mPaintLine;
    private String[] sensor = {"W", "N","E","S"};
    private Float degree;//角度
    private boolean work = true;
//对degree插入setter和getter方法
    public void setDegree(Float degree) {
        this.degree = degree;
    }

    public Float getDegree() {
        return degree;
    }
//两个构造器
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        SurfaceHolder holder = getHolder();//得到holder
        holder.addCallback(this);//绑定holder的回

        mPaintCircle = new Paint();
        mPaintCircle.setColor(Color.BLACK);
        mPaintCircle.setStyle(Paint.Style.STROKE);
        mPaintCircle.setStrokeWidth(5);

        mPaintText = new Paint();
        mPaintText.setColor(Color.RED);
        mPaintText.setStrokeWidth(10);
        mPaintText.setTextSize(20);

        mPaintLine = new Paint();
        mPaintLine.setColor(Color.GREEN);
        mPaintLine.setStrokeWidth(10);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
    }
// implements SurfaceHolder.Callback后实现下面的三个方法
    @Override
    public void surfaceCreated(final SurfaceHolder holder) {
        //启动线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (work) {
                    Canvas canvas = holder.lockCanvas();
                    //接下来绘制东西,相当于onDrawn()方法
                    canvas.drawColor(Color.GRAY);
                    canvas.drawCircle(width / 2, height / 2, 200, mPaintCircle);
                    canvas.drawCircle(width / 2, height / 2, 10, mPaintCircle);
                    for (int i = 1; i <= sensor.length; i++) {//用FOR循环画12条短线
                        canvas.save();//保存画布当前的状态
                        canvas.rotate(360 / 4 * i+degree, width / 2, height / 2);//旋转画布,每次转90度
                        canvas.drawText("" + sensor[i - 1], width / 2, height / 2 - 180, mPaintText);
                        canvas.restore();
                    }
                    canvas.save();
                    canvas.rotate(degree, width / 2, height / 2);//从activity中得到旋转的角度
                    canvas.drawLine(width / 2, height / 2, width / 2, height / 2 - 160, mPaintLine);
                    canvas.restore();
                    holder.unlockCanvasAndPost(canvas);
                    try {
                        Thread.sleep(40);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        holder.setFixedSize(this.width,this.height);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        work = false;
    }
}

2、在布局文件中声明MyView


    <com.my.administrator.myseneor.MyView
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

3、 MainActivity

public class MainActivity extends AppCompatActivity {
    private SensorManager sensorManager;
    private MyView myView;
    private float degree;
    float[] acceleromoterValues = new float[3];//加速度传感器的三个值
    float[] magneticValues = new float[3];//地磁传感器的三个值

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myView = (MyView) findViewById(R.id.view);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);//获得sensorManager的实例,sensorManager是所有传感器的管理器,有了它之后就可以调用getDefaultSensor方法得到任意的传感器类型了。
        Sensor magegeticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        //调用registerListener方法注册才能生效
        sensorManager.registerListener(listener, magegeticSensor, SensorManager.SENSOR_DELAY_GAME);
        sensorManager.registerListener(listener, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (sensorManager != null) {
            sensorManager.unregisterListener(listener);
        }
    }

    private SensorEventListener listener = new SensorEventListener() {

        @Override
        public void onSensorChanged(SensorEvent event) {
            //判断当前是加速度传感器还是地磁传感器
            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                //注意赋值时要调用clone()方法
                acceleromoterValues = event.values.clone();
            } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                magneticValues = event.values.clone();
            }
            float[] R = new float[9];
            float[] values = new float[3];
            SensorManager.getRotationMatrix(R, null, acceleromoterValues, magneticValues);
            SensorManager.getOrientation(R, values);
            //第一个values的值就是手机旋转的角度
            Log.d("MainActivity", "values[0] is" + Math.toDegrees(values[0]));
            degree = (float)-Math.toDegrees(values[0]);
            Log.d("MainActivity", "这里指针转过了" + degree);
            myView.setDegree(degree);//通过setDegree方法将角度传到myview中去,然后指针相应偏转
        }

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

        }
    };
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值