Reference version

This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

Expo Hinge

A library that provides the device hinge angle and status on Android foldables and iPhone Duo.

Android
iOS
Recommended version:
~58.0.2

expo-hinge exposes the hinge of a foldable device, such as an Android foldable or iPhone Duo, to the whole app. It reports the angle in degrees and whether the hinge is closed, partially open, or fully open. On Android, the hinge angle sensor provides the angle and Jetpack WindowManager's FoldingFeature provides the status. On iOS, a UIHingeInteraction on the app's window provides these values. For reacting to the hinge from one SwiftUI view, use the onHingeChange modifier from @expo/ui instead.

Status on Android

Android has no public API that reports a closed hinge, so the status is never closed on Android. Android reports the hinge state only while the app's window spans the fold. Otherwise, such as on the outer screen of a closed device, the status is unknown, but Android still reports the angle. To detect a closed device on Android, check for an angle near 0. Choose a threshold that suits your app, because device makers define their own ranges.

Installation

Terminal
- npx expo install expo-hinge
- yarn expo install expo-hinge
- pnpm expo install expo-hinge
- bun expo install expo-hinge

If you are installing this in an existing React Native app, make sure to install expo in your project.

Usage

import { useHinge } from 'expo-hinge'; import { StyleSheet, Text, View } from 'react-native'; export default function App() { const hinge = useHinge(); return ( <View style={styles.container}> <Text>{hinge ? `${hinge.status} at ${Math.round(hinge.angle)}°` : 'No hinge'}</Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, });

Use with Reanimated

The expo-hinge/reanimated entry provides the hinge as a Reanimated shared value. The UI thread updates this value on each hinge change and does not wait for the JavaScript thread. Animations that read it stay in sync with the hinge, even when the JavaScript thread is busy. This entry requires react-native-reanimated and react-native-worklets.

import { useAnimatedHinge } from 'expo-hinge/reanimated'; import Animated, { useAnimatedStyle } from 'react-native-reanimated'; export default function Lid() { const hinge = useAnimatedHinge(); const style = useAnimatedStyle(() => ({ transform: [{ rotate: `${(hinge.get()?.angle ?? 180) - 180}deg` }], })); return <Animated.View style={[{ width: 120, height: 8, backgroundColor: 'gray' }, style]} />; }

API

import * as Hinge from 'expo-hinge';

Hooks

useAnimatedHinge()

Android
iOS

Returns a Reanimated shared value with the live hinge state. The UI thread updates it with no JS-thread round trip, so animations that read it keep up with the hinge while the JS thread is busy. Import it from expo-hinge/reanimated, which requires react-native-reanimated and react-native-worklets.

Returns:
SharedValue<Hinge | null>

Example

const hinge = useAnimatedHinge(); const style = useAnimatedStyle(() => ({ transform: [{ rotate: `${hinge.get()?.angle ?? 180}deg` }], }));

useHinge()

Android
iOS

Returns the live hinge state and re-renders on every change. The first render already has the current value, since the native module caches it.

Returns:
Hinge | null

Example

const hinge = useHinge(); return <Text>{hinge ? `${hinge.status} at ${hinge.angle}°` : 'No hinge'}</Text>;

Methods

getHinge()

Android
iOS

Returns the current hinge state synchronously, or null when the API is unavailable, the device has no hinge, or the app's window provides no hinge updates.

Returns:
Hinge | null

Example

Hinge.getHinge(); // { angle: 120, status: 'partiallyOpen' }

isAvailable()

Android
iOS

Returns whether this build and OS can report the hinge: Android 11 (API level 30) or later, or iOS 27.1 or later, built with the iOS 27.1 SDK. It does not mean the device has a hinge, which getHinge() answers with a non-null value. Always false on web.

Returns:
boolean

Event subscriptions

addHingeListener(listener)

Android
iOS
ParameterTypeDescription
listener(event: HingeChangeEvent) => void

A callback that is invoked with a HingeChangeEvent.


Subscribes to hinge changes. The listener is called on every angle or status change, and with a null hinge when the window stops providing hinge updates. Use hinge state for interactions and effects, not for layout.

Returns:
EventSubscription

An EventSubscription whose remove() unsubscribes the listener.

addHingeWorkletListener(worklet)

Android
iOS
ParameterTypeDescription
worklet(event: HingeChangeEvent) => void

A worklet that is invoked with a HingeChangeEvent.


Subscribes a worklet to hinge changes. The worklet runs on the UI thread, synchronously with the native change, and never waits for the JS thread. Unlike addHingeListener, it also runs once with the current hinge right after the subscription. Throws an error when worklet is not a worklet. Import it from expo-hinge/reanimated, which requires react-native-reanimated and react-native-worklets.

Returns:
EventSubscription

An EventSubscription whose remove() unsubscribes the worklet.

Types

ExpoHingeModuleEvents

Android
iOS
PropertyTypeDescription
hingeChange(event: HingeChangeEvent) => void
-

Hinge

Android
iOS

State of the device hinge.

PropertyTypeDescription
anglenumber

The current angle of the hinge in degrees, where 0 is closed and 180 is flat. The rate and granularity of angle updates are system policy, so do not depend on a particular update frequency or precision. Prefer status when you only need to know whether the hinge is closed, partially open, or fully open, except on Android, where status is never closed. On Android, the angle comes from the hinge angle sensor.

statusHingeStatus

The current status of the hinge, determined by the system from the angle and device orientation.

HingeChangeEvent

Android
iOS
PropertyTypeDescription
hingeHinge | null

The current hinge, or null when the device has no hinge, the app's window provides no hinge updates, or, on Android, the device has no hinge angle sensor.

HingeStatus

Android
iOS

Literal type: string

Status of the device hinge, as reported by the state of Jetpack WindowManager's FoldingFeature on Android and by UIKit's UIHinge.Status on iOS. Android has no public API for a closed hinge, so it never reports closed. It reports unknown while the app's window does not span the fold, such as on the outer screen of a closed device. To detect a closed device on Android, check for an angle near 0 with a threshold that suits your app.

Acceptable values are: 'closed' | 'partiallyOpen' | 'fullyOpen' | 'unknown'