Read, lock, and watch the interface orientation
One.ScreenOrientation reads the orientation your app’s window actually
uses, requests a portrait or landscape lock while a screen needs one, and
reports changes. These values describe the interface, which can differ
from the physical device orientation when rotation lock is on.
On iOS it reads effectiveGeometry and requests geometry updates on the
active window scene. On Android it derives the value from display
rotation and locks through the activity’s requested orientation. On web
it reads screen.orientation and locks through the browser API.
import { useEffect } from 'react'import { One } from 'one'
function useLandscape() { useEffect(() => { One.ScreenOrientation.lock('landscapeLeft') return () => { void One.ScreenOrientation.unlock() } }, [])}Locking while a screen mounts and unlocking on unmount keeps the preference scoped to the screen that needs it.
getOrientation returns portrait, portrait upside down, landscape left,
landscape right, or unknown. lock takes the four concrete orientations
or landscape, which lets the platform pick a side, and resolves with
the orientation once the window reports a match. unlock releases the
request and restores manifest behavior, resolving with the current
orientation. The change listener fires only when the effective interface
orientation changes; remove it when its owner unmounts.
On iOS the request goes to the active window scene on the main thread.
Without an active scene the call rejects with
E_SCREEN_ORIENTATION_SCENE. The manifest bounds what iOS may use: set
native.app.orientation to allow both portrait and landscape, since a
portrait-only or landscape-only manifest limits runtime requests, and an
orientation outside the manifest or window rejects with
E_SCREEN_ORIENTATION_UNSUPPORTED. If the scene never reaches the
requested orientation, the call rejects with
E_SCREEN_ORIENTATION_TIMEOUT after ten seconds.
On Android a runtime lock overrides the manifest, so a manifest conflict never rejects; unsupported fires only on a display that does not rotate. The lock verifies against display rotation for ten seconds before timing out. On web, primary portrait and landscape map to portrait and landscape left, secondary values to the upside-down and right variants, and changes follow the orientation change event. Browser locks reject when unsupported, blocked by fullscreen policy, or unreached, and unlock rejects when the browser lacks it. Server rendering resolves unknown for reads, locks, and unlocks, and listeners return an inert remover.
| Methods | Type | Description |
|---|---|---|
getOrientation() => Promise<ScreenOrientationValue>The current interface orientation. | () => Promise<ScreenOrientationValue> | The current interface orientation. |
lock(orientation: ScreenOrientationLock) => Promise<ScreenOrientationValue>Request an orientation. Resolves once it matches. | (orientation: ScreenOrientationLock) => Promise<ScreenOrientationValue> | Request an orientation. Resolves once it matches. |
unlock() => Promise<ScreenOrientationValue>Release the lock. Resolves with the current value. | () => Promise<ScreenOrientationValue> | Release the lock. Resolves with the current value. |
addChangeListener(onChange: (orientation: ScreenOrientationValue) => void) => () => voidHear effective changes. Returns a remover. | (onChange: (orientation: ScreenOrientationValue) => void) => () => void | Hear effective changes. Returns a remover. |
The value is unknown, portrait, portraitUpsideDown, landscapeLeft,
or landscapeRight. The lock adds landscape for either landscape side.
| iOS | Android | Web | |
|---|---|---|---|
| Source | Window scene | Display rotation | Screen API |
| Lock | Scene geometry | Activity request | Browser lock |
| Manifest | Bounds requests | Overridden | No manifest |
| Timeout | Ten seconds | Ten seconds | Browser decides |
E_SCREEN_ORIENTATION_SCENE on iOS.import { useEffect } from 'react'import { One } from 'one'
function useVideoOrientation() { useEffect(() => { async function prefer() { try { await One.ScreenOrientation.lock('landscape') } catch { // stay in whatever orientation the device allows } } prefer() return () => { void One.ScreenOrientation.unlock() } }, [])}landscape lets the platform pick the side that matches how the viewer
holds the device. A rejected lock falls back to the current orientation
instead of breaking the screen.
import { useEffect, useState } from 'react'import { Text } from 'react-native'import { One } from 'one'
function OrientationLabel() { const [orientation, setOrientation] = useState('unknown')
useEffect(() => { One.ScreenOrientation.getOrientation().then(setOrientation) return One.ScreenOrientation.addChangeListener(setOrientation) }, [])
return <Text>Interface: {orientation}</Text>}The initial read seeds the state before the first change arrives, and the listener’s remover doubles as the effect cleanup. The listener fires only on effective changes, so renders stay quiet otherwise.
Edit this page on GitHub.