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