React Native 扫码组件react-native-camera与自定义UI界面动画套装
2018-01-19 15:24
921 查看
扫码这个功能在普通项目中用到的案例还是比较多的,签到、加好友、WebView跳转等等
针对扫码这个功能,react-native的前辈们已经封装好了可以跨平台的组件
react-native-camera
亲测是非常好用的,虽然有很多提Issue,但是最新的版本还是比较稳定的
给大家说一下我在用的时候遇到的一个自己挖的坑
因为我的项目有不止一个界面用到了这个功能,所以我在不同的导航器中用到了同一个界面,界面的key值也是相同的,导航倒是没有出现错乱,但是在打开Camera的时候会出现白屏,相机始终不能渲染出来,当然对Key值进行区分,这个问题也就解决了,刚开始以为是组件的问题,去官网一顿找相似的issue
好了,忘记这个issue继续说,UI,功能测试没问题之后发现这个customer界面是真的没做什么优化,真的很丑,所以,拿来微信的扫一扫功能来参考一下
![](https://img-blog.csdn.net/20180119145144354?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjg5Nzg4OTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
经过对一些功能的筛选,我们对一些细节进行了模仿
先看一下效果吧
![](https://img-blog.csdn.net/20180119145535258?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjg5Nzg4OTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
说一下具体进行的模仿模块
1、四周阴影和中间全透明的效果实现
实现这个效果我走了点弯路,实现方法也是比较麻烦,先给大家分享一下,我是将界面分成了5部分(View),中间框是一部分,四周是一部份
2、四个绿色的边框角
这四个边框角的原型是两个View,每个View是一条线
其实就是一横一竖,宽度和高度分别是2,这个是左上角的,右上角的边框是通过左上角的旋转角度而来
其他的处理方法类似
3、扫描线
扫描线就是一条线,然后赋予动画,
而且这个动画是由setInterval定时器进行驱动的
接下来我把项目代码脱敏之后给大家共享出来,供参考
针对扫码这个功能,react-native的前辈们已经封装好了可以跨平台的组件
react-native-camera
亲测是非常好用的,虽然有很多提Issue,但是最新的版本还是比较稳定的
给大家说一下我在用的时候遇到的一个自己挖的坑
因为我的项目有不止一个界面用到了这个功能,所以我在不同的导航器中用到了同一个界面,界面的key值也是相同的,导航倒是没有出现错乱,但是在打开Camera的时候会出现白屏,相机始终不能渲染出来,当然对Key值进行区分,这个问题也就解决了,刚开始以为是组件的问题,去官网一顿找相似的issue
好了,忘记这个issue继续说,UI,功能测试没问题之后发现这个customer界面是真的没做什么优化,真的很丑,所以,拿来微信的扫一扫功能来参考一下
经过对一些功能的筛选,我们对一些细节进行了模仿
先看一下效果吧
说一下具体进行的模仿模块
1、四周阴影和中间全透明的效果实现
实现这个效果我走了点弯路,实现方法也是比较麻烦,先给大家分享一下,我是将界面分成了5部分(View),中间框是一部分,四周是一部份
2、四个绿色的边框角
这四个边框角的原型是两个View,每个View是一条线
<View style={{ position: 'absolute', left: 0, top: 0 }}> <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} /> <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} /> </View>
其实就是一横一竖,宽度和高度分别是2,这个是左上角的,右上角的边框是通过左上角的旋转角度而来
<View style={{ position: 'absolute', right: 1, top: -1, transform: [{rotate: '90deg'}] }}> <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} /> <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} /> </View>
其他的处理方法类似
3、扫描线
扫描线就是一条线,然后赋予动画,
<Animated.View style={{ width: px2dp(500), height: px2dp(2), backgroundColor: '#37b44a', transform: [{ translateY: this.state.top.interpolate({ inputRange: [0, 1], outputRange: [0, px2dp(500)] }) }]}} />
而且这个动画是由setInterval定时器进行驱动的
setInterval(function () { Animated.timing(that.state.top, { toValue: 1, duration: 2200 }).start(() => that.setState({ top: new Animated.Value(0) })) }, 2260)
接下来我把项目代码脱敏之后给大家共享出来,供参考
class ScannerCodeScreen extends Component {
static navigationOptions = ({ navigation }) => {
return ({
title: '二维码扫描',
...ApplicationStyles.blackHeaderStyle,
headerLeft: <HeaderLeft navigation={navigation} color={Colors.C8} />
})
}
constructor (props) {
super(props)
this.state = {
firstLoad: true,
top: new Animated.Value(0),
isSigned: false
}
/** object */
this.resultUrl = null
/** function */
this.onBarCodeRead = this.onBarCodeRead.bind(this)
this.interval = null
}
componentDidMount () {
}
componentWillReceiveProps (nextProps) {
if (!this.props.isFocused && nextProps.isFocused) {
this.onFocus()
}
if (this.props.isFocused && !nextProps.isFocused) {
this.onBlur()
}
}
onFocus () {
this.props.toggleTabBarAction(false)
/** 获取视频、现场首页信息 */
if (this.state.firstLoad) {
this.setState({ firstLoad: false })
}
/** 定时器触发动画 */
const that = this
this.interval =
setInterval(function () { Animated.timing(that.state.top, { toValue: 1, duration: 2200 }).start(() => that.setState({ top: new Animated.Value(0) })) }, 2260)
}
onBlur () {
/** 清除定时任务 */
clearInterval(this.interval)
}
getQueryString (url, name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
var r = url.substr(1).match(reg)
if (r != null) {
return unescape(r[2])
}
return null
}
onBarCodeRead (e) {
/** 避免多次提交 */
console.log(e)
if (!this.resultUrl || this.resultUrl !== e.data) {
if (e.data.indexOf('http://www.baidu.com/') !== 0) {
this.props.toastAction('请扫描正确的二维码')
} else {
this.resultUrl = e.data
const id = this.getQueryString(e.data, 'id')
this.props.navigation.navigate('applicationMessage', { receiver: id })
this.resultUrl = null
}
}
}
barcodeReceived (e) {
console.log('Barcode: ' + e.data)
console.log('Type: ' + e.type)
}
render () {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }} >
<View>
<Camera
ref={(cam) => {
this.camera = cam
}}
onBarCodeRead={this.onBarCodeRead.bind(this)}
style={{ width, height, marginTop: 40 }}
aspect={Camera.constants.Aspect.fill}
/>
<View style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }}>
<View style={{ height: (height - px2dp(600)) / 2, backgroundColor: 'black', opacity: 0.5 }} />
<View style={{ flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center' }}>
<View style={{ height: px2dp(500), width: (width - px2dp(500)) / 2, backgroundColor: 'black', opacity: 0.5 }} />
<View style={{ height: px2dp(500), width: px2dp(500) }} >
<View style={{ position: 'absolute', left: 0, top: 0 }}> <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} /> <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} /> </View>
<View style={{ position: 'absolute', right: 1, top: -1, transform: [{rotate: '90deg'}] }}> <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} /> <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} /> </View>
<View style={{ position: 'absolute', left: 1, bottom: -1, transform: [{rotateZ: '-90deg'}] }}>
<View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
<View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
</View>
<View style={{ position: 'absolute', right: 0, bottom: 0, transform: [{rotateZ: '180deg'}] }}>
<View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
<View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
</View>
<Animated.View style={{ width: px2dp(500),
height: px2dp(2),
backgroundColor: '#37b44a',
transform: [{
translateY: this.state.top.interpolate({
inputRange: [0, 1],
outputRange: [0, px2dp(500)]
})
}]}} />
</View>
<View style={{ height: px2dp(500), width: (width - px2dp(500)) / 2, backgroundColor: 'black', opacity: 0.5 }} />
</View>
<View style={{ flex: 1, backgroundColor: 'black', opacity: 0.5, alignItems: 'center' }} >
<Text style={{ fontSize: FontSize(28), color: Colors.C5, marginTop: px2dp(40) }}>将二维码放入框内,即可自动扫描</Text>
</View>
</View>
</View>
</View>
)
}
}
相关文章推荐
- React Native开源特效动画封装库模块(lottie-react-native)
- React Native 下拉刷新添加自定义动画
- React Native 热更新的组件react-native-pushy
- React-native自定义安卓组件
- react native中利用Picker自定义日期组件(只包含年和月)
- 自定义crosswalk为react-native组件是出现Fatal signal 11 (SIGSEGV) at 0x0000003c (code=1)的问题
- React Native 自定义组件报错 has no propType for native prop
- react-native自定义原生组件
- React-Native系列——自定义View组件开发
- React Native学习-控制横竖屏第三方组件:react-native-orientation
- React Native 二维码扫描 react-native-camera的使用
- React Native学习-控制横竖屏第三方组件:react-native-orientation
- React native 的轮播图组件react-native-image-carousel的使用
- 详解React Native开源时间日期选择器组件(react-native-datetime)
- ReactNative自定义Avatar&Badge组件
- React Native自定义标题栏组件的实现方法
- React Native 之组件react-native-sound的使用
- [深入剖析React Native]React Native组件之Navigator
- Android React Native自定义组件的流程