10

How can I disable rotation only for specific views (e.g: when using Navigator) and not for the entire app?

The question here already addresses disabling rotation for the entire app

Community
  • 1
  • 1
Alon Burg
  • 2,500
  • 2
  • 27
  • 32

2 Answers2

5

With the react-native-orientation package, it's possible to lock the orientation to portrait/landscape. The package and documentation can be found here: https://github.com/yamill/react-native-orientation

Remember; you should not put your locking inside the rendering of scenes (nor the renderScene method). Since the Navigator re-renders all the scenes in the route stack, this would probably cause weird side effects for you. Rather, the locking/unlocking should be put in the code that interacts with the route stack (ie. calls the push/pop methods).

Alexander Kuzmin
  • 1,120
  • 8
  • 16
  • 1
    Is it still working? I found lots of forgotten issues, and the module's last update seems to be about 3 years ago – Felix Apr 27 '21 at 00:33
2

If your case is about more specific control over orientations of different screens in StackNavigator (something like Portrait -> LandscapeLeft -> LandscapeRight -> Portrait, and all the way back), here is a may-not-that-pretty solution:

  • packages needed: react-navigation, react-native-orientation;
  • define base screens as follow:

    // baseScreen.js
    import React, { Component } from "react";
    import Orientation from "react-native-orientation";
    
    export class PortraitScreen extends Component {
    
        constructor(props) {
            super(props);
            this._willFocusSubscription = this.props.navigation.addListener("willFocus", payload => {
                // lock to portrait when this screen is about to appear
                Orientation.lockToPortrait();
            })
        }
    
        componentWillUnmount() {
            // remove subscription when unmount
            this._willFocusSubscription.remove();
        }
    }
    
    export class LandscapeScreen extends Component {
    
        constructor(props) {
            super(props);
            this._willFocusSubscription = this.props.navigation.addListener("willFocus", payload => {
                // lock to landscape
                Orientation.lockToLandscape();
            })
        }
    
        componentWillUnmount() {
            // remove subscription either
            this._willFocusSubscription.remove();
        }
    }
    
  • define concrete screens which extends abovementioned base screen(s):

    // moduleScreens.js
    import React from "react";
    import { Button, View } from "react-native";
    import { PortraitScreen, LandscapeScreen } from "/path/to/baseScreen";
    
    export class VideoDescScreen extends PortraitScreen {
        render() {
            return (
                <View>
                    <Button 
                        title="watch video"
                        onPress={() => this.props.navigation.navigate("VideoPlayer")}    
                    />
                </View>
            )
        }
    }
    
    export class VideoPlayerScreen extends LandscapeScreen {
        render() {
            return <View>...</View>
        }
    }
    
  • create route like this:

    // route.js
    import React from "react";
    import { createStackNavigator } from "react-navigation";
    import { VideoDescScreen, VideoPlayerScreen } from "/path/to/moduleScreens";
    
    const stack = createStackNavigator(
        {
            VideoDesc: {
                screen: VideoDescScreen
            },
            VideoPlayer: {
                screen: VideoPlayerScreen
            }
        }
    )
    
  • How it works? According to doc, we observe event willFocus when screen is initialized, and each time this screen is about to appear (focused) in navigation, we lock device to our desired orientation, works for both PUSH(to) and POP(back from) behaviors.

Hope it helps.

Ke Yang
  • 881
  • 1
  • 12
  • 21