Android app that starts in phone's current orientation but doesn't reorient

49 Views Asked by At

I'm new to Android and making some toy apps to try things out for my own amusement.

I want to make an app that starts in whichever orientation the user is holding the phone but then stays in that orientation no matter which way the phone is rotated.

I'm experimenting with the android:screenOrientation and android:configChanges but can't seem to find a combo that does what I want.

  • I can lock it into either landscape or portrait but I don't want to dictate which it should be.
    android:screenOrientation="locked" locks it to portrait even if the phone is in landscape when I launch the app.
  • I can get it to start in the current orientation and ignore 90° turns, but it will still do a reorientation if I turn it upside down / 180°.

It's hard to Google because I just find lots of different questions display orientation and rotation but not my specific one. If it makes any difference I'm using Kotlin and need to support from Android 9.

1

There are 1 best solutions below

0
mohammad zarei matin On

You need to set the orientation programmatically based on the current orientation, in the onCreate method of your Activity:

class MainActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        requestedOrientation = getCurrentOrientation()         
    
        super.onCreate(savedInstanceState)
    }
}

The actual challenge is finding the current orientation. Android's orientation API only provides ORIENTATION_LANDSCAPE and ORIENTATION_PORTRAIT values, regardless of the device rotation degree. For example, both 90° and 270° rotations from normal portrait orientation will count as ORIENTATION_LANDSCAPE. So in case this covers your needs, you can use the following method:

private fun getCurrentOrientation() = 
    if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE)
        ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
    else
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT

In case you need to keep the actual rotation, you should use Display APIs:

private fun getCurrentOrientation(): Int {
    val rotation = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        display?.rotation ?: Surface.ROTATION_0
    } else {
        @Suppress("DEPRECATION")
        windowManager.defaultDisplay.rotation
    }

    return when(rotation) {
        Surface.ROTATION_90 -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
        Surface.ROTATION_180 -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
        Surface.ROTATION_270 -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
        else -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    }
}

Note that the above code is considering only mobile phones. The provided surface angle is relative to the device's "natural" orientation. 0 on a tablet is landscape, whereas 0 on a phone is portrait.