1import React from 'react'; 2import { NavigationEvents } from 'react-navigation'; 3import { Button, Platform, StyleSheet, Text, View } from 'react-native'; 4 5import { ScreenOrientation } from 'expo'; 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 ]} 110 type={this.state.type} 111 style={styles.preview} 112 /> 113 114 {this.state.haveDimensions && ( 115 <Svg.Svg height={this.state.canvasHeight} width={this.state.canvasWidth} style={styles.svg}> 116 <Svg.Circle 117 cx={this.state.canvasWidth! / 2} 118 cy={this.state.canvasHeight! / 2} 119 r={2} 120 strokeWidth={2.5} 121 stroke="#e74c3c" 122 fill="#f1c40f" 123 /> 124 {this.state.boundingBox && ( 125 <Svg.Rect 126 x={this.state.boundingBox.origin.x} 127 y={this.state.boundingBox.origin.y} 128 width={this.state.boundingBox.size.width} 129 height={this.state.boundingBox.size.height} 130 strokeWidth={2} 131 stroke="#9b59b6" 132 fill="none" 133 /> 134 )} 135 {circles} 136 </Svg.Svg> 137 )} 138 139 <View style={styles.toolbar}> 140 <Button color={BUTTON_COLOR} title="Direction" onPress={this.toggleType} /> 141 <Button 142 color={BUTTON_COLOR} 143 title="Orientation" 144 onPress={this.toggleScreenOrientationState} 145 /> 146 <Button color={BUTTON_COLOR} title="Alerting" onPress={this.toggleAlertingAboutResult} /> 147 </View> 148 </View> 149 ); 150 } 151 152 toggleType = () => 153 this.setState({ 154 type: 155 this.state.type === BarCodeScanner.Constants.Type.back 156 ? BarCodeScanner.Constants.Type.front 157 : BarCodeScanner.Constants.Type.back, 158 }) 159 160 handleBarCodeScanned = (data: any) => { 161 if (this.state.alerting) { 162 requestAnimationFrame(() => { 163 alert(JSON.stringify(data)); 164 }); 165 } 166 this.setState({ cornerPoints: data.cornerPoints, boundingBox: data.bounds }); 167 } 168} 169 170const styles = StyleSheet.create({ 171 container: { 172 flex: 1, 173 }, 174 preview: { 175 ...StyleSheet.absoluteFillObject, 176 backgroundColor: 'black', 177 }, 178 toolbar: { 179 position: 'absolute', 180 bottom: 0, 181 left: 0, 182 right: 0, 183 paddingVertical: 10, 184 paddingHorizontal: 10, 185 flexDirection: 'row', 186 justifyContent: 'space-between', 187 backgroundColor: 'rgba(255,255,255,0.2)', 188 }, 189 svg: { 190 position: 'absolute', 191 borderWidth: 2, 192 borderColor: 'red', 193 }, 194}); 195