1import React from 'react'; 2import { NavigationEvents } from 'react-navigation'; 3import { Button, Platform, StyleSheet, Text, View } from 'react-native'; 4 5import * as ScreenOrientation from 'expo-screen-orientation'; 6 7import * as Svg from 'react-native-svg'; 8import * as Permissions from 'expo-permissions'; 9import { BarCodeScanner } from 'expo-barcode-scanner'; 10 11const BUTTON_COLOR = Platform.OS === 'ios' ? '#fff' : '#666'; 12 13interface State { 14 isPermissionsGranted: boolean; 15 type: any; 16 cornerPoints?: any[]; 17 alerting: boolean; 18 haveDimensions: boolean; 19 canvasHeight?: number; 20 canvasWidth?: number; 21 boundingBox?: { 22 origin: { 23 x: number; 24 y: number; 25 }; 26 size: { 27 width: number; 28 height: number; 29 }; 30 }; 31} 32 33export default class BarcodeScannerExample extends React.Component<{}, State> { 34 static navigationOptions = { 35 title: '<BarCodeScanner />', 36 }; 37 38 canChangeOrientation = false; 39 40 readonly state: State = { 41 isPermissionsGranted: false, 42 type: BarCodeScanner.Constants.Type.back, 43 alerting: false, 44 haveDimensions: false, 45 }; 46 47 componentDidFocus = async () => { 48 const { status } = await Permissions.askAsync(Permissions.CAMERA); 49 this.setState({ isPermissionsGranted: status === 'granted' }); 50 } 51 52 toggleAlertingAboutResult = () => { 53 this.setState({ alerting: !this.state.alerting }); 54 } 55 56 toggleScreenOrientationState = () => { 57 if (this.canChangeOrientation) { 58 ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP); 59 } else { 60 ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.ALL); 61 } 62 this.canChangeOrientation = !this.canChangeOrientation; 63 } 64 65 setCanvasDimensions = (e: any) => { 66 this.setState({ 67 canvasWidth: e.nativeEvent.layout.width, 68 canvasHeight: e.nativeEvent.layout.height, 69 haveDimensions: true, 70 }); 71 } 72 73 render() { 74 if (!this.state.isPermissionsGranted) { 75 return ( 76 <View style={styles.container}> 77 <NavigationEvents onDidFocus={this.componentDidFocus} /> 78 <Text>You have not granted permission to use the camera on this device!</Text> 79 </View> 80 ); 81 } 82 83 const circles = []; 84 85 if (this.state.cornerPoints) { 86 for (const point of this.state.cornerPoints) { 87 circles.push( 88 <Svg.Circle 89 cx={point.x} 90 cy={point.y} 91 r={2} 92 strokeWidth={0.1} 93 stroke="gray" 94 fill="green" 95 /> 96 ); 97 } 98 } 99 100 return ( 101 <View style={styles.container}> 102 <BarCodeScanner 103 onLayout={this.setCanvasDimensions} 104 onBarCodeScanned={this.handleBarCodeScanned} 105 barCodeTypes={[ 106 BarCodeScanner.Constants.BarCodeType.qr, 107 BarCodeScanner.Constants.BarCodeType.pdf417, 108 BarCodeScanner.Constants.BarCodeType.code128, 109 BarCodeScanner.Constants.BarCodeType.code39, 110 ]} 111 type={this.state.type} 112 style={styles.preview} 113 /> 114 115 {this.state.haveDimensions && ( 116 <Svg.Svg height={this.state.canvasHeight} width={this.state.canvasWidth} style={styles.svg}> 117 <Svg.Circle 118 cx={this.state.canvasWidth! / 2} 119 cy={this.state.canvasHeight! / 2} 120 r={2} 121 strokeWidth={2.5} 122 stroke="#e74c3c" 123 fill="#f1c40f" 124 /> 125 {this.state.boundingBox && ( 126 <Svg.Rect 127 x={this.state.boundingBox.origin.x} 128 y={this.state.boundingBox.origin.y} 129 width={this.state.boundingBox.size.width} 130 height={this.state.boundingBox.size.height} 131 strokeWidth={2} 132 stroke="#9b59b6" 133 fill="none" 134 /> 135 )} 136 {circles} 137 </Svg.Svg> 138 )} 139 140 <View style={styles.toolbar}> 141 <Button color={BUTTON_COLOR} title="Direction" onPress={this.toggleType} /> 142 <Button 143 color={BUTTON_COLOR} 144 title="Orientation" 145 onPress={this.toggleScreenOrientationState} 146 /> 147 <Button color={BUTTON_COLOR} title="Alerting" onPress={this.toggleAlertingAboutResult} /> 148 </View> 149 </View> 150 ); 151 } 152 153 toggleType = () => 154 this.setState({ 155 type: 156 this.state.type === BarCodeScanner.Constants.Type.back 157 ? BarCodeScanner.Constants.Type.front 158 : BarCodeScanner.Constants.Type.back, 159 }) 160 161 handleBarCodeScanned = (data: any) => { 162 if (this.state.alerting) { 163 requestAnimationFrame(() => { 164 alert(JSON.stringify(data)); 165 }); 166 } 167 this.setState({ cornerPoints: data.cornerPoints, boundingBox: data.bounds }); 168 } 169} 170 171const styles = StyleSheet.create({ 172 container: { 173 flex: 1, 174 }, 175 preview: { 176 ...StyleSheet.absoluteFillObject, 177 backgroundColor: 'black', 178 }, 179 toolbar: { 180 position: 'absolute', 181 bottom: 0, 182 left: 0, 183 right: 0, 184 paddingVertical: 10, 185 paddingHorizontal: 10, 186 flexDirection: 'row', 187 justifyContent: 'space-between', 188 backgroundColor: 'rgba(255,255,255,0.2)', 189 }, 190 svg: { 191 position: 'absolute', 192 borderWidth: 2, 193 borderColor: 'red', 194 }, 195}); 196