locking到一个方向时获取手机方向

这很可能是另一个问题的重复,我只是努力找出要search的东西。

我的相机应用程序locking在横向模式(在清单中)像这样:

android:screenOrientation="landscape" 

不过,我仍然想旋转一些UI元素,当设备旋转成肖像(虽然android仍然会认为它的景观,但这是故意的)。

所以我试过这个检查方向

 int rotation = this.getWindowManager().getDefaultDisplay() .getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: Log.d("Rotation", "0"); break; case Surface.ROTATION_90: Log.d("Rotation", "90"); break; case Surface.ROTATION_180: Log.d("Rotation", "180"); break; case Surface.ROTATION_270: Log.d("Rotation", "270"); break; } 

不幸的是,无论我打开手机,它总是返回90。 有没有一个更强大的方法来获取定位,而不pipeAndroid“认为”的方向是什么?

Solutions Collecting From Web of "locking到一个方向时获取手机方向"

所以在我想到之后,我意识到我可以实现一个类似于Android自己用来确定方向的algorithm。 我使用onSenseorChangedcallback来实现

 public static final int UPSIDE_DOWN = 3; public static final int LANDSCAPE_RIGHT = 4; public static final int PORTRAIT = 1; public static final int LANDSCAPE_LEFT = 2; public int mOrientationDeg; //last rotation in degrees public int mOrientationRounded; //last orientation int from above private static final int _DATA_X = 0; private static final int _DATA_Y = 1; private static final int _DATA_Z = 2; private int ORIENTATION_UNKNOWN = -1; @Override public void onSensorChanged(SensorEvent event) { Log.d(TAG, "Sensor Changed"); float[] values = event.values; int orientation = ORIENTATION_UNKNOWN; float X = -values[_DATA_X]; float Y = -values[_DATA_Y]; float Z = -values[_DATA_Z]; float magnitude = X*X + Y*Y; // Don't trust the angle if the magnitude is small compared to the y value if (magnitude * 4 >= Z*Z) { float OneEightyOverPi = 57.29577957855f; float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi; orientation = 90 - (int)Math.round(angle); // normalize to 0 - 359 range while (orientation >= 360) { orientation -= 360; } while (orientation < 0) { orientation += 360; } } //^^ thanks to google for that code //now we must figure out which orientation based on the degrees Log.d("Oreination", ""+orientation); if (orientation != mOrientationDeg) { mOrientationDeg = orientation; //figure out actual orientation if(orientation == -1){//basically flat } else if(orientation <= 45 || orientation > 315){//round to 0 tempOrientRounded = 1;//portrait } else if(orientation > 45 && orientation <= 135){//round to 90 tempOrientRounded = 2; //lsleft } else if(orientation > 135 && orientation <= 225){//round to 180 tempOrientRounded = 3; //upside down } else if(orientation > 225 && orientation <= 315){//round to 270 tempOrientRounded = 4;//lsright } } if(mOrientationRounded != tempOrientRounded){ //Orientation changed, handle the change here mOrientationRounded = tempOrientRounded; } } 

它看起来比它更复杂,但只是知道它的工作原理(我会说,同样的系统工作)。 不要忘记在onResume和onPause中注册您的传感器更改事件监听器来加速计

对于检测方向,我使用这个注册到sensormanager:

 mSensorOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); mSensorManager.registerListener(this, mSensorOrientation, SensorManager.SENSOR_DELAY_NORMAL); 

然后这个检测方向的变化,在注释中你可以把你自己的方法实现。

常量:

 public static final int LYING = 0; public static final int LANDSCAPE_RIGHT = 1; public static final int PORTRAIT = 2; public static final int LANDSCAPE_LEFT = 3; public void onSensorChanged(SensorEvent event) { Sensor sensorEvent = event.sensor; if ((sensorEvent.getType() == Sensor.TYPE_ORIENTATION)) { float [] eventValues = event.values; // current orientation of the phone float xAxis = eventValues[1]; float yAxis = eventValues[2]; if ((yAxis <= 25) && (yAxis >= -25) && (xAxis >= -160)) { if (previousOrientation != PORTRAIT){ previousOrientation = PORTRAIT; // CHANGED TO PORTRAIT } } else if ((yAxis < -25) && (xAxis >= -20)) { if (previousOrientation != LANDSCAPE_RIGHT){ previousOrientation = LANDSCAPE_RIGHT; // CHANGED TO LANDSCAPE RIGHT } } else if ((yAxis > 25) && (xAxis >= -20)){ if (previousOrientation != LANDSCAPE_LEFT){ previousOrientation = LANDSCAPE_LEFT; // CHANGED TO LANDSCAPE LEFT } } } 

}

在做了一些研究并尝试了一些东西之后,我将Sensor设置为:

 mSensorOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 

Sensor.TYPE_ORIENTATION已被弃用,并根据来自不同人的一些示例代码来检索定位,从而给我带来不好的结果。 我真的不知道是否可以,但它对我有效。

@panavtec的翻译回答API 23, 以此作为参考

 class MyActivity extends Activity implements SensorEventListener { private SensorManager sensorManager; private float[] lastMagFields = new float[3];; private float[] lastAccels = new float[3];; private float[] rotationMatrix = new float[16]; private float[] orientation = new float[4]; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); } protected void onResume() { super.onResume(); sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_GAME); sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); } protected void onPause() { super.onPause(); sensorManager.unregisterListener(this); } public void onAccuracyChanged(Sensor sensor, int accuracy) { } public void onSensorChanged(SensorEvent event) { switch (event.sensor.getType()) { case Sensor.TYPE_ACCELEROMETER: System.arraycopy(event.values, 0, lastAccels, 0, 3); break; case Sensor.TYPE_MAGNETIC_FIELD: System.arraycopy(event.values, 0, lastMagFields, 0, 3); break; default: return; } if (SensorManager.getRotationMatrix(rotationMatrix, null, lastAccels, lastMagFields)) { SensorManager.getOrientation(rotationMatrix, orientation); float xAxis = (float) Math.toDegrees(orientation[1]); float yAxis = (float) Math.toDegrees(orientation[2]); int orientation = Configuration.ORIENTATION_UNDEFINED; if ((yAxis <= 25) && (yAxis >= -25) && (xAxis >= -160)) { Log.d(TAG, "Portrait"); orientation = Configuration.ORIENTATION_PORTRAIT; } else if ((yAxis < -25) && (xAxis >= -20)) { Log.d(TAG, "Landscape Right"); orientation = Configuration.ORIENTATION_LANDSCAPE; } else if ((yAxis > 25) && (xAxis >= -20)){ orientation = Configuration.ORIENTATION_LANDSCAPE; Log.d(TAG, "Landscape Left"); } } } }