Reputation: 720
What is the relationship between the degrees reported by the OrientationEventListener.onOrientationChanged and the Display Rotation as reported by WindowManager().getDefaultDisplay().getRotation.
Both of these return the orientation of the device in degrees. What is the relationship between those values and how should one interpret them?
Upvotes: 1
Views: 1021
Reputation: 720
So I did a little bit of digging around and wrote a helper class as below which can be an nested class within an Activity. The OrientationEventListener listens on changes in the Accelerometer data. If you hold a phone in its natural orientation (portrait / vertical), the orientation is 0. It gradually increases when you rotate the phone in clockwise direction. So when the left side is on top (landscape), the orientation is 90. When the phone is upside down it is 180. When the right side is up, it is 270.
While getRotation() is the the rotation of the screen from its "natural" orientation. Per the docs, the angle is the rotation of the drawn graphics on the screen, which is the opposite direction of the physical rotation of the device
. Hence when the phone is held in portrait mode / natural orientation, the rotation and orientation are both 0. If the left side is at the top, the orientation is 90, however the rotation is 270 since the drawn graphics is opposite in direction of the device rotation. Similarly, if the right side at the top, the orientation is 270 and rotation is 90. Interesting case: the phone is held upside down -- the orientation is 180 however the rotation is still 0. If the graphics are not redrawn when a phone is rotated, then the Display.getRotation() remains unchanged. This can also be verified from the code below. I am only printing the rotation and orientation when there is a change and orientation has been quantized into 4 values of 0, 90, 180, 270.
static final class CustomOrientationListener extends OrientationEventListener {
private static final String TAG = CustomOrientationListener.class.getSimpleName();
private int savedOrientation = Integer.MIN_VALUE;
private int savedRotation = Integer.MIN_VALUE;
AppCompatActivity activity;
public CustomOrientationListener(AppCompatActivity a) {
super(a);
activity = a;
}
/**
* Called when the orientation of the device has changed.
* orientation parameter is in degrees, ranging from 0 to 359.
* orientation is 0 degrees when the device is oriented in its natural position,
* 90 degrees when its left side is at the top, 180 degrees when it is upside down,
* and 270 degrees when its right side is to the top.
*/
@Override
public void onOrientationChanged(int orientation) {
orientation = normalizeOrientation(orientation);
if (savedOrientation != orientation) {
Log.i(TAG, "orientation: " + orientation);
savedOrientation = orientation;
}
int rotation = getRotationInDegrees(activity.getWindowManager().getDefaultDisplay().getRotation());
if (rotation != savedRotation) {
Log.i(TAG, "rotation: " + rotation);
savedRotation = rotation;
}
}
/**
* getRotation() Returns the rotation of the screen from its "natural" orientation. The returned value may be
* Surface.ROTATION_0 (no rotation), Surface.ROTATION_90, Surface.ROTATION_180, or Surface.ROTATION_270.
* For example, if a device has a naturally tall screen, and the user has turned it on its side to go into a
* landscape orientation, the value returned here may be either Surface.ROTATION_90 or Surface.ROTATION_270
* depending on the direction it was turned. The angle is the rotation of the drawn graphics on the screen,
* which is the opposite direction of the physical rotation of the device. For example, if the device is rotated
* 90 degrees counter-clockwise, to compensate rendering will be rotated by 90 degrees clockwise and thus the
* returned value here will be Surface.ROTATION_90.
*/
private static int getRotationInDegrees(int rotation) {
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
return degrees;
}
private static int normalizeOrientation(int degrees) {
if (degrees > 315 || degrees <= 45) {
return 0;
}
if (degrees > 45 && degrees <= 135) {
return 90;
}
if (degrees > 135 && degrees <= 225) {
return 180;
}
if (degrees > 225 && degrees <= 315) {
return 270;
}
throw new RuntimeException("The physics as we know them are no more. Watch out for anomalies.");
}
}
Upvotes: 2