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?
Asked
Active
Viewed 7,473 times
1 Answers
41
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(orientation) {
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)
}

Phil Dukhov
- 67,741
- 15
- 184
- 220
-
Shouldn't it be `DisposableEffect(orientation)`? So that the lambda is recomposed if the parameter changes? – m.reiter Mar 06 '23 at 15:40
-
Btw, this works also in the opposite direction: Most of my ui can only handle portrait mode, but for some i can allow landscape as an option using this with ActivityInfo.SCREEN_ORIENTATION_USER – m.reiter Mar 06 '23 at 15:45
-
@m.reiter yeah, if you wanna make it dynamic, you should pass orientation as the key. it's just a wrapper, so it works same as `activity.requestedOrientation` in plain android. if you have to change orientation often in your app, you may need to write some more complex system, which will store stack of requested orientations, but this basic technique should work in most cases – Phil Dukhov Mar 07 '23 at 00:52
-
Does the orientation change cause activity to reload and `onDispose` method to be called? I tried it to change orientation of WebView if user entered fullscreen mode and it immediately gets reverted to the `originalOrientation` – Bresiu May 10 '23 at 11:43
-
@Bresiu yes, `DisposableEffect` is getting reset on configuration change, you'll have to add more cumbersome logic – Phil Dukhov May 10 '23 at 13:18
-
it works in simple case but it is not working in case of a navigation because it will restore the orientation of the previous screen before the new one has set the correct orientation. – David Attias May 23 '23 at 15:51