Handle screen rotation without onConfiguration­Changed

Especially on camera view, we need to implement a view that can adapt to the screen’s orientation without having a splash of android native screen rotation handler. To do this, we just need to create an instance of OrientationEventListener with an abstract method onOrientationChanged. The method takes a parameter for the degree of screen 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 class event listeners that were based on OrientationEventListener.

The first class is SimpleOrientationEventListener that calculates the orientation of current screen and fires out by 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 that calculates which rotation degrees suit to view to rotate smoothly. This class extends from SimpleOrientationEventListener and calculates based on the onChanged method, then fires out via 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 get full code of two classes here.

To test the code, you have to set screenOrientation to landscape or portrait in AndroidManifest.xml or 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();
}