Abdo Rabah
Abdo Rabah

Reputation: 2062

How to detect screen orientation change in React Native?

I'm using Video from expo-av to display my videos. My goal is to display the video depending on the Orientation of the device of the user. I'm using ScreenOrientation from expo-screen-orientation so i can detect the rotation using the addOrientationChangeListener function. I tried my code below but i can't detect the change of the orientation. Any Help of how can i achieve my goal or what's wrong in my code?

import React, { Component } from 'react';
import {
  StyleSheet,
  View,
  TouchableOpacity,
  Image,
  Text,
  Alert,
  ScrollView,
  Dimensions
} from 'react-native';
import { Video } from 'expo-av';
import * as ScreenOrientation from 'expo-screen-orientation';
import NavigationHelper from '../../../../Helpers/NavigationHelper';

export default class VideoScreen extends Component {
  constructor(props) {
    super(props);
    /* enum Orientation {
      UNKNOWN = 0,
        PORTRAIT_UP = 1,
        PORTRAIT_DOWN = 2,
        LANDSCAPE_LEFT = 3,
        LANDSCAPE_RIGHT = 4
    } */
    this.state = {
      orientation: 1,
    };
  }

  async componentDidMount() {
    await this.detectOrientation();
    this.subscription = ScreenOrientation.addOrientationChangeListener(this.onOrientationChange);
    /* if (ScreenOrientation.Orientation.LANDSCAPE) {
      this.changeScreenLandscapeOrientation();
    } */
  }

  async componentWillUnmount() {
    await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT);
    ScreenOrientation.removeOrientationChangeListener(this.subscription);
    // this.changeScreenPortraitOrientation();
  }

  onOrientationChange = async (orientation) => {
    console.log('orientation changed');
    if (orientation === 3 || orientation === 4) {
      await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE);
    } else {
      await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT);
    }
    this.setState({ orientation });
  };

  detectOrientation= async () => {
    let orientation = await ScreenOrientation.getOrientationAsync();
    const screen = Dimensions.get('screen');
    if (orientation === 0) {
      orientation = screen.width > screen.height ? ScreenOrientation.Orientation.LANDSCAPE : ScreenOrientation.Orientation.PORTRAIT;
    }
    this.setState({ orientation });
    console.log(orientation);
  };

  render() {
    const { route } = this.props;
    const { videoUri } = route.params;

    if (!videoUri) {
      NavigationHelper.back();
    }

    return (
      <ScrollView style={styles.container}>
        <Video
          source={{ uri: videoUri }}
          rate={1.0}
          volume={1.0}
          isMuted={false}
          resizeMode={Video.RESIZE_MODE_CONTAIN}
          shouldPlay
          isLooping
          useNativeControls
          style={{ width: 300, height: 300, alignSelf: 'center' }}
          orientationChange={this.onOrientationChange}
        />
      </ScrollView>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#000000',
    flexDirection: 'column'
  },
});

Upvotes: 2

Views: 4447

Answers (2)

Defalt404
Defalt404

Reputation: 21

Your onOrientationChange() function its not working because you are locking the orientation before hand.

Once the orientation is locked the device is unable to detect the rotation change. For addOrientationChangeListener() to work the lockAsync has to be set on ALL or DEFAULT on an async function:

await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.DEFAULT);

Then you can pick up the change with:

const subscription = ScreenOrientation.addOrientationChangeListener((newOrientation) => {
        console.log('this variable will show everytime the screen rotates', newOrientation);
        setOrientation(newOrientation.orientationInfo.orientation);
        
        });

Upvotes: 0

Erick Maeda
Erick Maeda

Reputation: 347

Look at the library method getOrientationAsync()

export declare function getOrientationAsync(): Promise<Orientation>;

The orientation definition is

export declare enum Orientation {
    UNKNOWN = 0,
    PORTRAIT_UP = 1,
    PORTRAIT_DOWN = 2,
    LANDSCAPE_LEFT = 3,
    LANDSCAPE_RIGHT = 4
}

So, it already returns the integer that refers to the correct orientation. Maybe what you want to do is just remove the brackets between the orientation:

    let orientation = await ScreenOrientation.getOrientationAsync(); 

Upvotes: 2

Related Questions