React Native相机扫码
我最近一直在学习RN,当然中间也遇到了很多问题 ,下面是关于RN扫码的一些坑,觉得还是把这些坑都写出来,方便 RN的初学者。
react-native-camera
首先,进行依赖下载安装
npm install react-native-camera --save
权限配置
-
首先找到 android/app/src/main/AndroidManifest.xml 此目录文件,在该文件中添加如下代码
<uses-permission android:name="android.permission.CAMERA" />
-
然后找到 app/build.gradle 此文件,在该文件中添加如下代码
missingDimensionStrategy 'react-native-camera', 'general' implementation project(path: ':react-native-camera')
分别是在defaultConfig和dependencies中添加
defaultConfig{ missingDimensionStrategy 'react-native-camera', 'general' }
dependencies{ implementation project(path: ':react-native-camera') }
-
最后找到 android/settings.gradle 此文件,在该文件中添加
include ':react-native-camera' project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android')
-
此时,准备工作已全部完成,可以进行相关业务逻辑代码编写
文件代码
import {RNCamera} from 'react-native-camera';
import React, {useCallback, useEffect, useRef, useState} from 'react';
import {StyleSheet, Animated, View, Text, Button, Easing} from 'react-native';
import navigate from '../../utils/NavigateUtil';
import ModalSelect from '../../components/ModalSelect';
import List from '../../components/List';
import {gh} from '../../utils/autoSize';
import Vibrate, {VibratePress} from '../../utils/vibrate';
export default function Camera() {
const [flash, setFlash] = useState(false);
const lastScannedDataRef = useRef(null);
const moveAnim = useRef(new Animated.Value(-2)).current;
const [showModal, setShowModal] = useState(false);
const [dataList, setDataList] = useState([]);
/** 扫描框动画*/
const startAnimation = () => {
Animated.sequence([
Animated.timing(moveAnim, {
toValue: 200,
duration: 1500,
easing: Easing.linear,
useNativeDriver: false,
}),
Animated.timing(moveAnim, {
toValue: -1,
duration: 1500,
easing: Easing.linear,
useNativeDriver: false,
}),
]).start(() => startAnimation());
};
// 开始调用一次
useEffect(() => {
startAnimation();
}, []);
const onBarCodeRead = useCallback(
(result: {data: string}) => {
const {data} = result;
if (data && data !== lastScannedDataRef.current) {
//此处,可以根据自己的需求修改,当拿到数据后,该执行什么样的逻辑,
// setShowModal(true);
// const arr = data.split(',');
// const obj: any = {};
// for (let i = 0; i < arr.length; i++) {
// obj['field' + (i + 1)] = arr[i];
// }
// const dataList = Object.values(obj)
// .filter(value => value !== '')
// .map(value => ({item: value}));
// setDataList(dataList);
}
},
[navigate],
);
return (
<>
<View style={styles.container}>
<RNCamera
captureAudio={false}
autoFocus={RNCamera.Constants.AutoFocus.on}
style={[styles.preview]}
type={RNCamera.Constants.Type.back}
flashMode={
flash
? RNCamera.Constants.FlashMode.torch
: RNCamera.Constants.FlashMode.off
}
onBarCodeRead={onBarCodeRead}
//此处是类型,即相机可以识别的码类型
barCodeTypes={[
RNCamera.Constants.BarCodeType.qr,
RNCamera.Constants.BarCodeType.code128,
RNCamera.Constants.BarCodeType.code39,
RNCamera.Constants.BarCodeType.code93,
RNCamera.Constants.BarCodeType.ean13,
RNCamera.Constants.BarCodeType.ean8,
RNCamera.Constants.BarCodeType.pdf417,
RNCamera.Constants.BarCodeType.upc_e,
RNCamera.Constants.BarCodeType.interleaved2of5,
RNCamera.Constants.BarCodeType.itf14,
RNCamera.Constants.BarCodeType.aztec,
RNCamera.Constants.BarCodeType.datamatrix,
]}>
<View
style={{
width: 500,
height: 220,
backgroundColor: 'rgba(0,0,0,0.5)',
}}
/>
<View style={[{flexDirection: 'row'}]}>
<View
style={{
backgroundColor: 'rgba(0,0,0,0.5)',
height: 200,
width: 200,
}}
/>
<View style={{width: 200, height: 200}}>
<Animated.View
style={[styles.border, {transform: [{translateY: moveAnim}]}]}
/>
</View>
<View
style={{
backgroundColor: 'rgba(0,0,0,0.5)',
height: 200,
width: 200,
}}
/>
</View>
<View
style={{
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
width: 500,
alignItems: 'center',
}}>
<Text style={styles.rectangleText}>
将二维码放入框内,即可自动扫描
</Text>
<Button
onPress={() => {
setFlash(!flash);
}}
title={(flash ? '关闭' : '打开') + '闪光灯'}
/>
</View>
</RNCamera>
</View>
//此处也可根据需求修改,这里是将拿到的数据以弹框的形式展现出来
{showModal && (
<ModalSelect
cancel={() => {
Vibrate.btn();
setShowModal(false);
}}
title={'选择'}
RenderList={() => {
return (
<View
style={{
width: '100%',
height: '100%',
paddingTop: gh(10),
paddingBottom: gh(10),
}}>
<List
data={dataList}
titleKey={'item'}
onPress={data => {
const d = data.item;
console.log(d);
setShowModal(false);
navigate('Manufacturer', {partNumber: d});
}}
itemAlign="center"
/>
</View>
);
}}
/>
)}
</>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
},
preview: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
rectangleContainer: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
},
rectangle: {
height: 200,
width: 200,
borderWidth: 1,
borderColor: '#fcb602',
backgroundColor: 'transparent',
borderRadius: 10,
},
rectangleText: {
flex: 0,
color: '#fff',
marginTop: 10,
},
border: {
flex: 0,
width: 196,
height: 2,
backgroundColor: '#fcb602',
borderRadius: 50,
},
});
入口文件
<Button title='测试按钮' onPress={async () => {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
//跳转至扫码组件,即可开始扫码
navigate('Camera');
} else {
console.log('拒绝');
return;
}
}} />
ok,此时扫码功能已正常实现。如果有问题,欢迎评论交流。