Reputation: 13254
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
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
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
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
Reputation: 725
Try to setRequestedOrientation to SCREEN_ORIENTATION_SENSOR when exit from fullscreen ! setting OrientationEventListener may cause some unexpected resources usage.
Upvotes: -1
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