1import { Platform, Subscription } from 'expo-modules-core'; 2import * as ScreenOrientation from 'expo-screen-orientation'; 3import React from 'react'; 4import { ScrollView, Text } 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 <ScrollView style={{ padding: 10 }}> 131 {orientation !== undefined && ( 132 <Text>Orientation: {ScreenOrientation.Orientation[orientation]}</Text> 133 )} 134 {orientationLock !== undefined && ( 135 <Text>OrientationLock: {ScreenOrientation.OrientationLock[orientationLock]}</Text> 136 )} 137 {this.getScreenOrientationLockOptions().map((o) => ( 138 <ListButton key={o.key} onPress={() => this.lock(o.value)} title={o.key} /> 139 ))} 140 <ListButton 141 key="lockPlatformAsync Example" 142 onPress={this.lockPlatformExample} 143 title="Apply a custom native lock" 144 /> 145 <ListButton 146 key="doesSupport" 147 onPress={this.doesSupport} 148 title="Check Orientation.PORTRAIT_DOWN support" 149 /> 150 <ListButton 151 key="updateCurrentOrientationAndLock" 152 onPress={this.updateCurrentOrientationAndLock} 153 title="Update current orientation and lock" 154 /> 155 </ScrollView> 156 ); 157 } 158} 159