1import { Platform, Subscription } from 'expo-modules-core'; 2import * as ScreenOrientation from 'expo-screen-orientation'; 3import React from 'react'; 4import { ScrollView, Text, SafeAreaView } from 'react-native'; 5 6import ListButton from '../components/ListButton'; 7 8interface State { 9 orientation?: ScreenOrientation.Orientation; 10 orientationLock?: ScreenOrientation.OrientationLock; 11} 12 13// See: https://github.com/expo/expo/pull/10229#discussion_r490961694 14// eslint-disable-next-line @typescript-eslint/ban-types 15export default class ScreenOrientationScreen extends React.Component<{}, State> { 16 static navigationOptions = { 17 title: 'ScreenOrientation', 18 }; 19 20 readonly state: State = {}; 21 22 listener?: Subscription; 23 24 async componentDidMount() { 25 this.listener = ScreenOrientation.addOrientationChangeListener( 26 ({ orientationInfo, orientationLock }) => { 27 this.setState({ 28 orientation: orientationInfo.orientation, 29 orientationLock, 30 }); 31 } 32 ); 33 34 await this.updateCurrentOrientationAndLock(); 35 } 36 37 updateCurrentOrientationAndLock = async () => { 38 const [orientation, orientationLock] = await Promise.all([ 39 ScreenOrientation.getOrientationAsync(), 40 ScreenOrientation.getOrientationLockAsync(), 41 ]); 42 43 // update state 44 this.setState({ 45 orientation, 46 orientationLock, 47 }); 48 }; 49 50 updateOrientationAsync = async () => { 51 this.setState({ 52 orientation: await ScreenOrientation.getOrientationAsync(), 53 }); 54 }; 55 56 componentWillUnmount() { 57 if (this.listener) { 58 this.listener.remove(); 59 } 60 } 61 62 lock = async (orientation: ScreenOrientation.OrientationLock) => { 63 if (Platform.OS === 'web') { 64 // most web browsers require fullscreen in order to change screen orientation 65 await document.documentElement.requestFullscreen(); 66 } 67 68 await ScreenOrientation.lockAsync(orientation).catch(console.warn); // on iPhoneX PortraitUpsideDown would be rejected 69 70 if (Platform.OS === 'web') { 71 await document.exitFullscreen(); 72 } 73 74 await this.updateCurrentOrientationAndLock(); 75 }; 76 77 lockPlatformExample = async () => { 78 if (Platform.OS === 'web') { 79 // most web browsers require fullscreen in order to change screen orientation 80 await document.documentElement.requestFullscreen(); 81 } 82 83 await ScreenOrientation.lockPlatformAsync({ 84 screenOrientationLockWeb: ScreenOrientation.WebOrientationLock.LANDSCAPE, 85 screenOrientationArrayIOS: [ 86 ScreenOrientation.Orientation.PORTRAIT_DOWN, 87 ScreenOrientation.Orientation.LANDSCAPE_RIGHT, 88 ], 89 screenOrientationConstantAndroid: 8, // reverse landscape 90 }).catch((e) => alert(e)); // on iPhoneX PortraitUpsideDown would be rejected 91 92 if (Platform.OS === 'web') { 93 await document.exitFullscreen(); 94 } 95 96 await this.updateCurrentOrientationAndLock(); 97 }; 98 99 doesSupport = async () => { 100 const result = await ScreenOrientation.supportsOrientationLockAsync( 101 ScreenOrientation.OrientationLock.PORTRAIT_DOWN 102 ).catch(console.warn); 103 alert(`Orientation.PORTRAIT_DOWN supported: ${JSON.stringify(result)}`); 104 }; 105 106 getScreenOrientationLockOptions(): { 107 key: string; 108 value: ScreenOrientation.OrientationLock; 109 }[] { 110 const orientationOptions = [ 111 ScreenOrientation.OrientationLock.DEFAULT, 112 ScreenOrientation.OrientationLock.ALL, 113 ScreenOrientation.OrientationLock.PORTRAIT, 114 ScreenOrientation.OrientationLock.PORTRAIT_UP, 115 ScreenOrientation.OrientationLock.PORTRAIT_DOWN, 116 ScreenOrientation.OrientationLock.LANDSCAPE, 117 ScreenOrientation.OrientationLock.LANDSCAPE_LEFT, 118 ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT, 119 ]; 120 121 return orientationOptions.map((orientation) => ({ 122 key: ScreenOrientation.OrientationLock[orientation], 123 value: orientation, 124 })); 125 } 126 127 render() { 128 const { orientation, orientationLock } = this.state; 129 return ( 130 <SafeAreaView> 131 <ScrollView style={{ padding: 10 }}> 132 {orientation !== undefined && ( 133 <Text>Orientation: {ScreenOrientation.Orientation[orientation]}</Text> 134 )} 135 {orientationLock !== undefined && ( 136 <Text>OrientationLock: {ScreenOrientation.OrientationLock[orientationLock]}</Text> 137 )} 138 {this.getScreenOrientationLockOptions().map((o) => ( 139 <ListButton key={o.key} onPress={() => this.lock(o.value)} title={o.key} /> 140 ))} 141 <ListButton 142 key="lockPlatformAsync Example" 143 onPress={this.lockPlatformExample} 144 title="Apply a custom native lock" 145 /> 146 <ListButton 147 key="doesSupport" 148 onPress={this.doesSupport} 149 title="Check Orientation.PORTRAIT_DOWN support" 150 /> 151 <ListButton 152 key="updateCurrentOrientationAndLock" 153 onPress={this.updateCurrentOrientationAndLock} 154 title="Update current orientation and lock" 155 /> 156 </ScrollView> 157 </SafeAreaView> 158 ); 159 } 160} 161