Search code examples
androidandroid-activityorientationandroid-sensors

setRequestedOrientation, but still change according to sensor


I would like to simulate youtube video-view behaviour in terms of handling screen orientation.

use cases:
p1. when user press maximise -> activity always goes into landscape
p2. when user press minimise -> activity always goes into portrait
p3. when user rotates the device -> screen orientation should change accordingly even if p1 or p2 was applied before.

Currently I use:

 @Override
 public void onClick(View view) {
     if (getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT) {
         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
     } else {
         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
     }

However this locks the orientation permanently and fails p3.


Solution

  • After playing around for a while I have found the right solution. First of all - the problem is that android locks the screen after setRequestedOrientation call, you can't have a mix of both, the only to do it is to do everything manually.

    Here is how:

    class PlayerOrientationListener extends OrientationEventListener {
        PlayerOrientationListener() {
            super(VideoPlayerActivity.this);
        }
    
        @Override
        public void onOrientationChanged(int orientation) {
            int threshold = 5;
            if (Math.abs(orientation - 0) < threshold) orientation = 0;
            else if (Math.abs(orientation - 90) < threshold) orientation = 90;
            else if (Math.abs(orientation - 180) < threshold) orientation = 180;
            else if (Math.abs(orientation - 270) < threshold) orientation = 270;
    
            switch (orientation) {
                case 0:
                    if (!orientationLandscapeLocked) {
                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                        orientationPortraitLocked = false;
                    }
                    break;
                case 90:
                    if (!orientationPortraitLocked) {
                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
                        orientationLandscapeLocked = false;
                    }
                    break;
                case 180:
                    if (!orientationLandscapeLocked) {
                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
                        orientationPortraitLocked = false;
                    }
                    break;
                case 270:
                    if (!orientationPortraitLocked) {
                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                        orientationLandscapeLocked = false;
                    }
                    break;
            }
        }
    }
    

    and activity code:

    View.OnClickListener onExpandClick = new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT) {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
                    orientationLandscapeLocked = true;
                    orientationPortraitLocked = false;
                } else {
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
                    orientationPortraitLocked = true;
                    orientationLandscapeLocked = false;
                }
            }
        };
    btnExpandVideo.setOnClickListener(onExpandClick);
    
    orientationListener = new PlayerOrientationListener();
    orientationListener.enable();