react-native-orientation-locker

repository·master·Indexed 21 days ago

https://github.com/wonday/react-native-orientation-locker

A cross-platform React Native module (v1.7.0) to listen for device orientation changes, retrieve current orientation, and lock the screen to specific orientations such as Portrait and Landscape. It provides an imperative API, a declarative <OrientationLocker> component, and hooks like useOrientationChange and useDeviceOrientationChange for functional components.

Tokens
5.9K
Snippets
24
Records
28
Agent score
71%

What's inside react-native-orientation-locker

  1. Configure Android for react-native-orientation-locker

    master

    Android requires updates to three different files to handle orientation changes correctly.

    1. Update AndroidManifest.xml

    Add android:configChanges="keyboard|keyboardHidden|orientation|screenSize" to your activity:

    <activity
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize">

    2. Update MainActivity.java

    Implement the onConfigurationChanged method to broadcast orientation changes:

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Intent intent = new Intent("onConfigurationChanged");
        intent.putExtra("newConfig", newConfig);
        this.sendBroadcast(intent);
    }

    3. Update MainApplication.java

    Register the orientation activity lifecycle callbacks in onCreate:

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(OrientationActivityLifecycle.getInstance());
    }
    @Override
    public void onCreate() {
        registerActivityLifecycleCallbacks(OrientationActivityLifecycle.getInstance());
    }
  2. Configure iOS for react-native-orientation-locker

    master

    To support orientation locking on iOS, you must update your AppDelegate files.

    For RN 0.77 and above (Swift)

    1. In AppDelegate.swift, add the supportedInterfaceOrientationsFor method:
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
      return Orientation.getOrientation()
    }
    1. In your Bridging Header file, add:
    #import "Orientation.h"

    For RN 0.76 and below (Objective-C)

    1. In AppDelegate.m, import the header:
    #import "Orientation.h"
    1. Implement the supportedInterfaceOrientationsForWindow method:
    - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
      return [Orientation getOrientation];
    }
    #import "Orientation.h"
    
    @implementation AppDelegate
    
    - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
      return [Orientation getOrientation];
    }
    
    @end
  3. How the OrientationLocker stack works

    master

    The OrientationLocker component uses an internal stack to manage orientation requests.

    1. Mounting: When a component with <OrientationLocker> mounts, its requested orientation is pushed onto a global stack.
    2. Resolution: The library iterates through the stack from the most recent entry to the oldest. The first non-empty orientation found in the stack is applied to the device.
    3. Unmounting: When a component unmounts, it is removed from the stack, and the library re-evaluates the stack to apply the next available orientation.

    This pattern ensures that if a specific screen requires LANDSCAPE, the device will return to its previous orientation (e.g., PORTRAIT) automatically once that screen is closed.

  4. Troubleshooting orientation issues

    master

    iOS

    • Library not found error: If you see ld: library not found for -lRCTOrientation-tvOS, remove it from your linked libraries and frameworks.
    • iPad Delay: orientationDidChange may be delayed on iPads if upside down is enabled. Disable upside down for iPad to resolve this.

    Android

    • Fullscreen Requirement: If you encounter java.lang.IllegalStateException: Only fullscreen activities can request orientation, ensure your activity is set to fullscreen.

    Windows

    • Locking: Locking to an orientation only works on devices in tablet mode.
    • Sensors: getDeviceOrientation() will return UNKNOWN if the device lacks an orientation sensor.
  5. Retrieve current orientation and lock state

    master

    Use these methods to query the current state of the device or the library's lock status.

    • getOrientation(callback): Retrieves the current UI orientation via a callback.
    • getDeviceOrientation(callback): Retrieves the current physical device orientation via a callback.
    • getAutoRotateState(callback): Android only. Retrieves the auto-rotate state.
    • isLocked(): Returns a boolean indicating if the orientation is currently locked by this library.
    OrientationLocker.getOrientation((orientation) => {
      console.log("Current orientation: ", orientation);
    });
    
    if (OrientationLocker.isLocked()) {
      console.log("Orientation is locked");
    }
  6. Use orientation hooks

    master

    Use built-in hooks to respond to orientation changes within functional components.

    • useOrientationChange(callback): Hook for addOrientationListener events (UI orientation).
    • useDeviceOrientationChange(callback): Hook for addDeviceOrientationListener events (Physical device orientation).
    function SomeComponent() {
      useOrientationChange((o) => {
        // Handle orientation change
      });
    
      useDeviceOrientationChange((o) => {
        // Handle device orientation change
      });
    }
  7. Use the `<OrientationLocker>` reactive component

    master

    The <OrientationLocker> component allows you to declaratively manage orientation. Multiple components can be mounted; their props are merged in the order they were mounted, similar to the <StatusBar> component.

    Props:

    • orientation: The desired orientation (e.g., PORTRAIT, LANDSCAPE).
    • onChange: Callback triggered when the UI orientation changes.
    • onDeviceChange: Callback triggered when the device orientation changes.
    import React, { useState } from "react";
    import { OrientationLocker, PORTRAIT, LANDSCAPE } from "react-native-orientation-locker";
    
    export default function App() {
      return (
        <OrientationLocker
          orientation={PORTRAIT}
          onChange={orientation => console.log('onChange', orientation)}
          onDeviceChange={orientation => console.log('onDeviceChange', orientation)}
        />
      );
    }
  8. Listen to device orientation changes

    master

    Use addDeviceOrientationListener to track the physical orientation of the device. Unlike UI orientation, this callback can still be called even when lockToXXX is active.

    Possible return values:

    • PORTRAIT
    • LANDSCAPE-LEFT
    • LANDSCAPE-RIGHT
    • PORTRAIT-UPSIDEDOWN
    • UNKNOWN
    const deviceListener = OrientationLocker.addDeviceOrientationListener((deviceOrientation) => {
      console.log("Device Orientation changed: ", deviceOrientation);
    });
    
    // To stop listening:
    OrientationLocker.removeDeviceOrientationListener(deviceListener);
  9. Listen to orientation changes

    master

    You can subscribe to UI orientation changes using addOrientationListener. Note that if you use lockToXXX methods, the callback will not be triggered until unlockAllOrientations is called. The listener will force a resend of the event when locking or unlocking orientations.

    Possible return values:

    • PORTRAIT
    • LANDSCAPE-LEFT
    • LANDSCAPE-RIGHT
    • PORTRAIT-UPSIDEDOWN
    • UNKNOWN
    const orientationListener = OrientationLocker.addOrientationListener((orientation) => {
      console.log("UI Orientation changed: ", orientation);
    });
    
    // To stop listening:
    OrientationLocker.removeOrientationListener(orientationListener);