OrientationEventListener与Display.getRotation

时间:2017-08-20 15:27:00

标签: android orientation accelerometer screen-orientation screen-rotation

OrientationEventListener.onOrientationChanged报告的度数与WindowManager().getDefaultDisplay().getRotation报告的展示轮次之间的关系是什么?

这两个都以度为单位返回设备的方向。这些价值观之间的关系是什么?应该如何解释它们?

1 个答案:

答案 0 :(得分:2)

所以我做了一些挖掘并编写了一个如下所示的辅助类,它可以是一个Activity中的嵌套类。 OrientationEventListener侦听changes in the Accelerometer data。如果您以自然方向(纵向/垂直)握住手机,则方向为0.当您以顺时针方向旋转手机时,手机会逐渐增大。因此,当左侧位于顶部(横向)时,方向为90.当手机上下颠倒时,它为180.当右侧上升时,它为270.

虽然getRotation()是屏幕旋转的自然"取向。根据文档,the angle is the rotation of the drawn graphics on the screen, which is the opposite direction of the physical rotation of the device。因此,当手机处于纵向模式/自然方向时,旋转和方向均为0.如果左侧位于顶部,则方向为90,但旋转为270,因为绘制的图形与方向相反。设备旋转。类似地,如果右侧在顶部,方向是270并且旋转是90.有趣的情况:手机被倒置 - 方向是180但是旋转仍然是0.如果手机没有重新绘制图形旋转,然后Display.getRotation()保持不变。这也可以通过以下代码进行验证。我只是在有变化时打印旋转和方向,并且方向已被量化为4个值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.");
    }
}