Handle screen rotation without onConfiguration­Changed

Especially for camera views, we need to implement a view that can adapt to the screen’s orientation without relying on the native Android screen rotation handler. To achieve this, we create an instance of OrientationEventListener with an abstract method onOrientationChanged. This method takes a parameter representing the screen’s degree from 0 to 359, and -1 for screen flipping.

Example:

// MainActivity OrientationEventListener mListener;
void onCreate(Bundle savedInstanceState){
    ...

    mListener = new OrientationEventListener(this){
        public void onOrientationChanged(int orientation){
            System.out.println(orientation);
        }
    };
}

From this point, I created two shortcut classes based on OrientationEventListener.

The first class is SimpleOrientationEventListener, which calculates the current screen orientation and triggers the onChanged abstract method in onOrientationChanged. Below is the method.

@Override
public final void onOrientationChanged(int orientation) {
    if (orientation < 0) {
        return; // Flip screen, Not take account
    }

    int curOrientation;

    if (orientation <= 45) {
        curOrientation = ORIENTATION_PORTRAIT;
    } else if (orientation <= 135) {
        curOrientation = ORIENTATION_LANDSCAPE_REVERSE;
    } else if (orientation <= 225) {
        curOrientation = ORIENTATION_PORTRAIT_REVERSE;
    } else if (orientation <= 315) {
        curOrientation = ORIENTATION_LANDSCAPE;
    } else {
        curOrientation = ORIENTATION_PORTRAIT;
    }
    if (curOrientation != lastOrientation) {
        onChanged(lastOrientation, curOrientation);
        lastOrientation = curOrientation;
    }
}

The second class is RotateOrientationEventListener, which calculates the appropriate rotation degrees for smooth view rotation. This class extends SimpleOrientationEventListener and uses the onChanged method to determine the rotation, then triggers the onRotateChanged abstract method.

@Override
public final void onChanged(int lastOrientation, int orientation) {
    int startDeg = lastOrientation == 0
            ? orientation == 3 ? 360 : 0
            : lastOrientation == 1 ? 90
            : lastOrientation == 2 ? 180
            : 270; // don't know how, but it works
    int endDeg = orientation == 0
            ? lastOrientation == 1 ? 0 : 360
            : orientation == 1 ? 90
            : orientation == 2 ? 180
            : 270; // don't know how, but it works

    onRotateChanged(startDeg, endDeg);
}

You can find the full code for both classes here.

To test the code, set screenOrientation to landscape or portrait in AndroidManifest.xml or use setRequestedOrientation in the activity.

Bonus: This is an example of how to apply the startDeg and endDeg above to views:

private void rotateView(View view, int startDeg, int endDeg) {
    view.setRotation(startDeg);
    view.animate().rotation(endDeg).start();
}