这可能很容易与另一个问题重复,我只是在努力弄清楚要搜索什么。
我的相机应用程序已锁定在横向模式(在清单中),如下所示:
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。是否有更强大的方法来获得方向,无论Android“认为”的方向是什么?
答案 0 :(得分:8)
所以在我考虑之后,我意识到我可以实现一个与Android本身用来确定方向类似的算法。我是使用onSenseorChanged回调
来做的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中注册加速度计
答案 1 :(得分:3)
对于检测方向,我使用它来注册到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
}
}
}
}
答案 2 :(得分:2)
在做了一些研究并尝试了一些东西之后,当我将传感器设置为:
时,它对我来说很有用mSensorOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
不推荐使用Sensor.TYPE_ORIENTATION,根据来自不同人员的一些示例代码检索方向,我给出了不良结果。我真的不知道它是否合适,但它对我有用。
答案 3 :(得分:0)
使用this作为参考
,将@panavtec的答案翻译为API 23class 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");
}
}
}
}
答案 4 :(得分:0)
这是@Jameo答案的略微修改的Kotlin版本。我需要度数来计算具有锁定方向的活动中的相机旋转。请你也投票给他。
private var rotationDeg: Int = 0
private var rotationRoundedClockwise: Int = 0
override fun onSensorChanged(event: SensorEvent) {
Timber.d("Sensor Changed")
val newRotationDeg = calculateNewRotationDegree(event)
//^^ thanks to google for that code
// now we must figure out which orientation based on the degrees
Timber.d("rotation: $newRotationDeg")
if (newRotationDeg != rotationDeg) {
rotationDeg = newRotationDeg
rotationRoundedClockwise = calculateRoundedRotation(newRotationDeg)
}
Timber.d("rotationRoundedClockwise: $rotationRoundedClockwise")
}
private val X_AXIS_INDEX = 0
private val Y_AXIS_INDEX = 1
private val Z_AXIS_AXIS = 2
private val ORIENTATION_UNKNOWN = -1
private fun calculateRoundedRotation(newRotationDeg: Int): Int {
return if (newRotationDeg <= 45 || newRotationDeg > 315) { // round to 0
0 // portrait
} else if (newRotationDeg in 46..135) { // round to 90
90 // clockwise landscape
} else if (newRotationDeg in 136..225) { // round to 180
180 // upside down portrait
} else if (newRotationDeg in 226..315) { // round to 270
270 // anticlockwise landscape
} else {
0
}
}
private fun calculateNewRotationDegree(event: SensorEvent): Int {
val values = event.values
var newRotationDeg = ORIENTATION_UNKNOWN
val X = -values[X_AXIS_INDEX]
val Y = -values[Y_AXIS_INDEX]
val Z = -values[Z_AXIS_AXIS]
val 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) {
val ONE_EIGHTY_OVER_PI = 57.29577957855f
val angle = Math.atan2((-Y).toDouble(), X.toDouble()).toFloat() * ONE_EIGHTY_OVER_PI
newRotationDeg = 90 - Math.round(angle)
// normalize to 0 - 359 range
while (newRotationDeg >= 360) {
newRotationDeg -= 360
}
while (newRotationDeg < 0) {
newRotationDeg += 360
}
}
return newRotationDeg
}
private fun getCameraRotation(): Int {
return when (rotationRoundedClockwise) {
0 -> 90
90 -> 180
180 -> 270
270 -> 0
else -> 90
}
}
以下是如何倾听事件。
override fun onCreate() {
super.onCreate()
(activity?.getSystemService(SENSOR_SERVICE) as? SensorManager)?.let {
sensorManager = it
}
}
override fun onResume() {
super.onResume()
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL)
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}