How to force orientation for some screens in Jetpack Compose?

Viewed 2983

With jetpack compose navigation, I suppose it may become a single activity app. How to force orientation only for certain composables (screens)? Say if I want to force landscape only when playing video and not other screens? Without navigation, can declare orientation in manifest but with navigation where we can specify this, possibly, at the composable level?

1 Answers

You can get current activity from LocalContext, and then update requestedOrientation.

To set the desired orientation when the screen appears and bring it back when it disappears, use DisposableEffect:

@Composable
fun LockScreenOrientation(orientation: Int) {
    val context = LocalContext.current
    DisposableEffect(Unit) {
        val activity = context.findActivity() ?: return@DisposableEffect onDispose {}
        val originalOrientation = activity.requestedOrientation
        activity.requestedOrientation = orientation
        onDispose {
            // restore original orientation when view disappears
            activity.requestedOrientation = originalOrientation
        }
    }
}

fun Context.findActivity(): Activity? = when (this) {
    is Activity -> this
    is ContextWrapper -> baseContext.findActivity()
    else -> null
}

Usage:

@Composable
fun Screen() {
    LockScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
}
Related