NPike
NPike

Reputation: 13254

Toggling fullscreen & orientation like YouTube

I am trying to mimic the behavior of the YouTube Android app when the "fullscreen" button is clicked in the video player:

It seems that if I force the rotation to landscape or portrait using:

getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

or

getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

... I immediately lose the ability to detect sensor orientation changes (i.e. once the user is in landscape, and they want to manually rotate the device back to portrait).

If I change the requested orientation to unspecified or sensor in onConfigurationChanged, the orientation briefly flips to landscape/portrait (whatever I requested from above) and then snaps back to the orientation that matches how the device is held.

Any thoughts on how to achieve my goals above?

Upvotes: 15

Views: 5537

Answers (5)

Buntupana
Buntupana

Reputation: 1023

This modification of Alexander code is working better for me

   object : OrientationEventListener(requireContext()) {
        override fun onOrientationChanged(orientation: Int) {
            val isPortrait = orientation > 345 || orientation < 15 || orientation in 165..195
            val isLandscape = orientation in 255..285 || orientation in 75..105
            if (
                (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT && isPortrait) ||
                (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE && isLandscape)
            ) {
                lifecycleScope.launch {
                    // adding a delay to avoid orientation change glitch
                    delay(200)
                    activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
                }
            }
        }
    }

Upvotes: 2

Syed Zeeshan
Syed Zeeshan

Reputation: 570

/**
     * -1 -> Unknown
     * 1 -> Portrait
     * 0 -> Landscape
     */
    var previousOrientation = -1

    val orientationEventListener: OrientationEventListener =
        object : OrientationEventListener(this) {
            override fun onOrientationChanged(orientation: Int) {

                val isPortrait = (orientation > 340 || orientation < 20 || orientation in 160..200) &&
                        requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
                val isLandscape = (orientation in 250..290 || orientation in 70..110) &&
                        requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE

                if (isPortrait || isLandscape) {
                    lifecycleScope.launch {
                        if (previousOrientation == -1) {
                            previousOrientation = if (isPortrait) 1 else 0
                        }
                        delay(700)
                        val currentOrientation = if (isPortrait) 1 else 0
                        if (previousOrientation == currentOrientation) {
                            previousOrientation = -1
                            requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
                        }
                    }
                }
            }
        }
    orientationEventListener.enable()

This one handles the orientation glitch more properly. this code is improved version of what @Buntupana posted

Upvotes: 0

Alexander Mazyarik
Alexander Mazyarik

Reputation: 596

Big tnx to havch

It is gold, I was stuck on that for 5 hours. Here is my kotlin piece of code to deal with it.

orientationEventListener = object: OrientationEventListener(this) {
            override fun onOrientationChanged(orientation: Int) {
                val isPortrait = orientation > 300 || orientation < 60 || orientation in 120..240

                if ((requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT && isPortrait) ||
                    (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE && !isPortrait)){
                    requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
                }
            }
        }
        orientationEventListener.enable()

Upvotes: 5

Ehsan Chavoshi
Ehsan Chavoshi

Reputation: 725

Try to setRequestedOrientation to SCREEN_ORIENTATION_SENSOR when exit from fullscreen ! setting OrientationEventListener may cause some unexpected resources usage.

Upvotes: -1

havchr
havchr

Reputation: 1142

I had the excact same problem. What I ended up with was using an OrientationListener to detect when the user had actually tilted the phone to landscape and then setting the orientation to SCREEN_ORIENTATION_SENSOR.

OrientationEventListener orientationEventListener = 
new OrientationEventListener(getActivity()) {
    @Override
    public void onOrientationChanged(int orientation) {
        int epsilon = 10;
        int leftLandscape = 90;
        int rightLandscape = 270;
        if(epsilonCheck(orientation, leftLandscape, epsilon) ||
           epsilonCheck(orientation, rightLandscape, epsilon)){
                getMainActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
            }
        }

        private boolean epsilonCheck(int a, int b, int epsilon) {
            return a > b - epsilon && a < b + epsilon;
        }
    };
    orientationEventListener.enable();

Here is the documentation for OrientationEventListener : Documentation

You would also need to add checks for portrait , because you described needing that in your original post.

Upvotes: 27

Related Questions