Screen orientation refers to how a device is held or positioned, typically about its vertical and horizontal axes. Screen orientation is important because it determines how a device’s screen is displayed and how users can interact with it.
For example, a device in portrait orientation will display the screen vertically, while a device in landscape orientation will display the screen horizontally. In this article, we will explore lock orientation in modern React Native applications and how to ensure that apps can only be displayed in a certain screen orientation.
Jump ahead:
The expo-screen-orientation package is built by the Expo team. It includes all the tools to manage the screen orientation of a device, including fetching the current orientation, changing the orientation, and locking the screen orientation to a specific state.
To use the expo-screen-orientation, you need to install it in your React Native project by using the following commands:
$ yarn add expo-screen-orientation $ npm install --save expo-screen-orientation
$ npx expo install expo-screen-orientation
To get the current orientation of a screen in a React Native app, use the Expo-designed ScreenOrientation
API, which provides information about the device’s screen orientation. You can use the getOrientationAsync
property to get the current orientation of the screen, which will return an integer as its value, as shown below:
Orientation.Unknown = 0 Orientation.PORTRAIT_UP = 1 Orientation.PORTRAIT_DOWN = 2 Orientation.LANDSCAPE_LEFT = 3 Orientation.LANDSCAPE_RIGHT = 4
Here is a code snippet to fetch the current screen orientation:
const checkOrientation = async () => { const orientation = await ScreenOrientation.getOrientationAsync(); console.log("orientation", orientation); };
To check for updates to the screen orientation, use the addOrientationChangeListener
method from the ScreenOrientation
API. This will pass a callback
function that will be called whenever the orientation changes. This callback
function will receive an event object containing information about the new orientation, which you can use to update your app’s UI or handle the orientation change in another way.
Here is an example of how you can use these APIs to handle orientation changes in your app:
import { StatusBar } from "expo-status-bar"; import { StyleSheet, Text, View } from "react-native"; import * as ScreenOrientation from "expo-screen-orientation"; import { useEffect, useState } from "react"; export default function App() { const [orientation, setOrientation] = useState(null); useEffect(() => { checkOrientation(); const subscription = ScreenOrientation.addOrientationChangeListener( handleOrientationChange ); return () => { ScreenOrientation.removeOrientationChangeListeners(subscription); }; }, []); const checkOrientation = async () => { const orientation = await ScreenOrientation.getOrientationAsync(); setOrientation(orientation); }; const handleOrientationChange = (o) => { setOrientation(o.orientationInfo.orientation); }; console.log(orientation); return ( <View style={styles.container}> <Text>ORIENTATION: {orientation}</Text> <StatusBar style="auto" /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center", }, });
Here’s what the portrait and landscape screen orientations look like:
In this example, we use the ScreenOrientation
API to get the screen’s current orientation and to listen for orientation changes. When the orientation changes, we update the orientation
state variable using the setOrientation
Hook.
Then, we use this state variable to display the current orientation in the log. The response of the listener is in the form of the object as shown below:
{ "orientationInfo":{ "horizontalSizeClass":1, "orientation":4, "verticalSizeClass":1 }, "orientationLock":0 }
We also use the ScreenOrientation
API to lock the screen to portrait orientation, which means that the user will not be able to rotate the screen to landscape orientation. This can be useful if you want to prevent the app from being displayed in a landscape orientation or to ensure that the app always displays in a specific orientation.
To disable orientation changes or set a single orientation for your React Native app, you can use the ScreenOrientation
API. This API provides methods for controlling the orientation of the screen.
You can use the lockAsync
method to lock the screen in a specific orientation or the unlockAsync
method to allow the screen to be rotated to any orientation.
Below is the example for locking the orientation programmatically:
import { StatusBar } from "expo-status-bar"; import { StyleSheet, Text, View } from "react-native"; import * as ScreenOrientation from "expo-screen-orientation"; import { useEffect, useState } from "react"; export default function App() { const [orientation, setOrientation] = useState(1); useEffect(() => { lockOrientation(); }, []); const lockOrientation = async () => { await ScreenOrientation.lockAsync( ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT ); const o = await ScreenOrientation.getOrientationAsync(); setOrientation(o); }; return ( <View style={styles.container}> <Text>Locked Screen orientation: {orientation}</Text> <StatusBar style="auto" /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center", }, });
In bare React Native apps, we have another way to lock the screen orientations of the apps.
Open the AndroidManifest.xml
file and set android:screenOrientation="portrait"
to lock the screen in portrait or android:screenOrientation="landscape"
to lock the screen in landscape mode. Here’s what that should look like:
<activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:exported="true" android:theme="@style/Theme.App.SplashScreen" android:screenOrientation="portrait" >
To manage screen orientation in iOS, open Xcode and check the orientation that you need for your app in General > Deployment Info:
Now, what if one needs to update the orientation programmatically? For example, when playing a video, you would want it displayed in landscape mode for a better viewing experience for the users.
Here is an easy-to-use example to update and lock the screen orientation on button taps and clicks using expo-screen-orientation:
import { StatusBar } from "expo-status-bar"; import { StyleSheet, Text, TouchableOpacity, View } from "react-native"; import * as ScreenOrientation from "expo-screen-orientation"; import { useEffect, useState } from "react"; export default function App() { const [orientation, setOrientation] = useState(null); useEffect(() => { checkOrientation(); const subscription = ScreenOrientation.addOrientationChangeListener( handleOrientationChange ); return () => { ScreenOrientation.removeOrientationChangeListeners(subscription); }; }, []); const checkOrientation = async () => { const orientation = await ScreenOrientation.getOrientationAsync(); setOrientation(orientation); }; const changeOrientation = async (newOrientation) => { console.log("newOrientation: ", newOrientation); await ScreenOrientation.lockAsync(newOrientation); }; const handleOrientationChange = (o) => { setOrientation(o.orientationInfo.orientation); }; console.log(orientation); return ( <View style={styles.container}> <Text>ORIENTATION: {orientation}</Text> <TouchableOpacity style={[styles.btn, { marginTop: 15 }]} onPress={() => changeOrientation(ScreenOrientation.OrientationLock.PORTRAIT_UP) } > <Text style={styles.txt}>Tap to Portrait orientation</Text> </TouchableOpacity> <TouchableOpacity style={styles.btn} onPress={() => changeOrientation(ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT) } > <Text style={styles.txt}>Tap to Landscape orientation</Text> </TouchableOpacity> <StatusBar style="auto" /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center", }, btn: { padding: 10, }, txt: { fontSize: 16, color: "blue", }, });
And, voila! Below is a video clip of what we achieved with the code above:
In conclusion, screen orientation is an important aspect of device interaction. Expo APIs allow you to get the current orientation, listen for orientation changes, and control the screen’s orientation in your React Native apps.
These APIs help you create more engaging and user-friendly apps that adapt to different orientations and provide a consistent UX. Overall, the expo-screen-orientation package is a valuable tool for any React Native app that needs to manage screen orientation.
LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowIn this article, you’ll learn how to set up Hoppscotch and which APIs to test it with. Then we’ll discuss alternatives: OpenAPI DevTools and Postman.
Learn to migrate from react-native-camera to VisionCamera, manage permissions, optimize performance, and implement advanced features.
SOLID principles help us keep code flexible. In this article, we’ll examine all of those principles and their implementation using JavaScript.
JavaScript’s Date API has many limitations. Explore alternative libraries like Moment.js, date-fns, and the new Temporal API.
2 Replies to "Managing orientation changes in React Native apps"
Would be better if you mentioned commenting out the default orientation: portrait inside app.json on iOS. If this isn’t done, then the code doesn’t work, as orientation modes don’t change.
Suggest add to the beginning. Otherwise its a reasonably good article.
Will the library works without expo? I mean I have an app in react native and I’m not using expo. I want one screen in both orientations and rest of the app in portrait. How I can do that ? Can you update the article for this? I need solution for both ios and android