React Native 自定义控件之验证码和Toast
推荐:自定义“验证码”控件
雕虫小技--自定义“验证码”控件 “验证码”在登录的时候,经常用到,如果把“她”封装成控件,是不是很爽呢? 但是,我一般不喜欢封装得太厉害的“她”,因
2019阿里云双12.12最低价产品入口(新老用户均可),
地址:https://www.aliyun.com/minisite/goods
React Native通过近两年的迭代和维护,最新版本已经到了0.45.1,关于最新版本的介绍请查看我之前的博客:0.45新特性。话说回来,尽管迭代的挺快,但还是有很多坑,很多基础的组件和API还是不完善。
今天给大家带来的自定义小专题,其实对于React Native来说,自定义组件的过程更像是Android、iOS的组合控件。大体步骤有如下几个步骤(不完全准确,但是方向大体准确):
1,定义构造函数constructor;
2,定义组件属性propTypes;
3,绘制界面;
4,添加更新界面逻辑等
自定义Toast
在系统组件中,RN为我们提供了ToastAndroid组件,但是对于iOS好像并没有直接提供,这时候我们就想到了自定义控件了。如下图所示:
我们之前讲过Animated组件,这个组件可以实现渐变,缩放,旋转等动画效果,在这里,我们可以用它来实现Toast的功能。比如,显示两秒后消失,为了对显示的位置进行设置,我们还可以设置显示的位置,所以绘制render的代码如下:
render() {
let top;
switch (this.props.position){
case 'top':
top=160;
break;
case 'center':
top=height /2;
break;
case 'bottom':
top=height - 160;
break;
}
let view = this.state.isShow ?
<View
style={[styles.container,{top:top}]}
pointerEvents="none"
>
<Animated.View
style={[styles.content,{opacity:this.state.opacityValue}]}
>
<Text style={styles.text}>{this.state.text}</Text>
</Animated.View>
</View> : null;
return view;
}
显示时长控制方法:
show(text, duration) {
if(duration>=DURATION.LENGTH_LONG){
this.duration=DURATION.LENGTH_LONG;
}else {
this.duration=DURATION.LENGTH_SHORT;
}
this.setState({
isShow: true,
text: text,
});
this.isShow=true;
this.state.opacityValue.setValue(OPACITY)
this.close();
}
完整代码:
我在网上看到了有其他网友的实现方式,他是继承Ext.form.field.Text来实现的,经过测试,这种实现方式确实可以完成验证码输入框的功能,但是有两个地方有待完善
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */
import React, {Component,PropTypes} from 'react';
import {
StyleSheet,
View,
Animated,
Dimensions,
Text,
} from 'react-native'
export const DURATION = {LENGTH_LONG: 2000, LENGTH_SHORT: 500};
const {height, width} = Dimensions.get('window');
const OPACITY=0.6;
const dismissKeyboard = require('dismissKeyboard')
export default class ToastUtil extends Component {
static propTypes = {
position: PropTypes.oneOf([
'top',
'center',
'bottom',
]),
}
static defaultProps = {
position:'center',
}
constructor(props) {
super(props);
this.state = {
isShow: false,
text: '',
opacityValue:new Animated.Value(OPACITY),
}
}
show(text, duration) {
if(duration>=DURATION.LENGTH_LONG){
this.duration=DURATION.LENGTH_LONG;
}else {
this.duration=DURATION.LENGTH_SHORT;
}
this.setState({
isShow: true,
text: text,
});
this.isShow=true;
this.state.opacityValue.setValue(OPACITY)
this.close();
}
close() {
if(!this.isShow)return;
this.timer && clearTimeout(this.timer);
this.timer = setTimeout(() => {
Animated.timing(
this.state.opacityValue,
{
toValue: 0.0,
duration:1000,
}
).start(()=>{
this.setState({
isShow: false,
});
this.isShow=false;
});
}, this.duration);
}
componentWillUnmount() {
this.timer && clearTimeout(this.timer);
}
render() {
let top;
switch (this.props.position){
case 'top':
top=160;
break;
case 'center':
top=height /2;
break;
case 'bottom':
top=height - 160;
break;
}
let view = this.state.isShow ?
<View
style={[styles.container,{top:top}]}
pointerEvents="none"
>
<Animated.View
style={[styles.content,{opacity:this.state.opacityValue}]}
>
<Text style={styles.text}>{this.state.text}</Text>
</Animated.View>
</View> : null;
return view;
}
}
const styles = StyleSheet.create({
container: {
position: 'absolute',
left: 0,
right: 0,
alignItems: 'center',
},
content: {
backgroundColor: 'black',
opacity: OPACITY,
borderRadius: 5,
padding: 10,
},
text:{
color:'white'
},
})
如何使用:
<Toast ref="toast"/>
//省略...
<Text style={styles.styleText} onPress={()=>{
this.refs.toast.show('你点击了忘记密码!',3000);}}>
忘记密码?
</Text>
//省略...
获取验证码
在很多应用开发中都会涉及到获取手机验证码的场景,例如登录或者注册获取验证码。如下图:
那么按照自定义组件的流程,先添加构造函数,并定义必须的一些字段(相关属性),并完成初始化:
static propTypes = {
style: PropTypes.object,//style属性
textStyle: Text.propTypes.style,//文本文字
onClick: PropTypes.func,//点击事件
disableColor: PropTypes.string,//倒计时过程中颜色
timerTitle: PropTypes.string,//倒计时文本
enable: React.PropTypes.oneOfType([React.PropTypes.bool,React.PropTypes.number])
};
2,构造函数:
constructor(props) {
super(props)
this.state = {
timerCount: this.props.timerCount || 60,//默认倒计时时间
timerTitle: this.props.timerTitle || '获取验证码',
counting: false,
selfEnable: true,
};
this.shouldStartCountting = this.shouldStartCountting.bind(this)
this.countDownAction = this.countDownAction.bind(this)
}
3,添加绘制界面代码:
render() {
const {onClick, style, textStyle, disableColor} = this.props;
const {counting, timerTitle, selfEnable} = this.state;
return (
<TouchableOpacity activeOpacity={counting ? 1 : 0.8} onPress={() => {
if (!counting &&selfEnable) {
this.setState({selfEnable: false});
this.shouldStartCountting(true);
};
}}>
<View
style={styles.styleCodeView}>
<Text
style={[{fontSize: 12}, textStyle, {color: ((!counting && selfEnable) ? textStyle.color : disableColor || 'gray')}]}>{timerTitle}</Text>
</View>
</TouchableOpacity>
)
}
4,添加逻辑代码:
shouldStartCountting(shouldStart) {
if (this.state.counting) {
return
}
if (shouldStart) {
this.countDownAction()
this.setState({counting: true, selfEnable: false})
} else {
this.setState({selfEnable: true})
}
}
//倒计时逻辑
countDownAction() {
const codeTime = this.state.timerCount;
this.interval = setInterval(() => { const timer = this.state.timerCount - 1 if (timer === 0) { this.interval && clearInterval(this.interval); this.setState({ timerCount: codeTime, timerTitle: this.props.timerTitle || '获取验证码', counting: false, selfEnable: true }) } else { this.setState({ timerCount: timer, timerTitle: `重新获取(${timer}s)`, }) } }, 1000) }
说明:
shouldStartCountting:回调函数,接受一个Bool类型的参数
1,shouldStartCountting(true),开始倒计时,倒计时结束时自动恢复初始状态
2,shouldStartCountting(false), 按钮的selfEnable会立即被置为true
所以,获取验证码的完整代码如下:
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, {Component,PropTypes} from 'react';
import {
Text,
StyleSheet,
View,
TouchableOpacity,
} from 'react-native';
var Dimensions = require('Dimensions');
var screenWidth = Dimensions.get('window').width;
export default class TimerButton extends Component {
constructor(props) {
super(props)
this.state = {
timerCount: this.props.timerCount || 60,
timerTitle: this.props.timerTitle || '获取验证码',
counting: false,
selfEnable: true,
};
this.shouldStartCountting = this.shouldStartCountting.bind(this)
this.countDownAction = this.countDownAction.bind(this)
}
static propTypes = {
style: PropTypes.object,
textStyle: Text.propTypes.style,
onClick: PropTypes.func,
disableColor: PropTypes.string,
timerTitle: PropTypes.string,
enable: React.PropTypes.oneOfType([React.PropTypes.bool,React.PropTypes.number])
};
countDownAction() {
const codeTime = this.state.timerCount;
this.interval = setInterval(() => { const timer = this.state.timerCount - 1 if (timer === 0) { this.interval && clearInterval(this.interval); this.setState({ timerCount: codeTime, timerTitle: this.props.timerTitle || '获取验证码', counting: false, selfEnable: true }) } else { this.setState({ timerCount: timer, timerTitle: `重新获取(${timer}s)`, }) } }, 1000) } shouldStartCountting(shouldStart) { if (this.state.counting) { return } if (shouldStart) { this.countDownAction() this.setState({counting: true, selfEnable: false}) } else { this.setState({selfEnable: true}) } } componentWillUnmount() { clearInterval(this.interval) } render() { const {onClick, style, textStyle, disableColor} = this.props; const {counting, timerTitle, selfEnable} = this.state; return ( <TouchableOpacity activeOpacity={counting ? 1 : 0.8} onPress={() => { if (!counting &&selfEnable) { this.setState({selfEnable: false}); this.shouldStartCountting(true); }; }}> <View style={styles.styleCodeView}> <Text style={[{fontSize: 12}, textStyle, {color: ((!counting && selfEnable) ? textStyle.color : disableColor || 'gray')}]}>{timerTitle}</Text> </View> </TouchableOpacity> ) } } const styles = StyleSheet.create({ container: { flex: 1, marginTop: 20 }, styleCodeView: { height: 28, width: screenWidth*0.22, borderColor: '#dc1466', borderWidth: 1, borderRadius: 5, justifyContent: 'center', alignItems: 'center', }, styleTextCode: { fontSize: 12, color: '#dc1466', textAlign: 'center', }, });
如何使用?
import TimerButton from './TimerButton'
var Dimensions = require('Dimensions');
var screenWidth = Dimensions.get('window').width;
//省略...
<TimerButton
style={{width: screenWidth*0.2,marginRight: 10}}
timerCount={60}
textStyle={{color: '#dc1466'}}
onclick={(start)=>{
}}/>
首先在components下建立一个文件,暂时取名为:ckd.php 文件类容如下: <php class CkdComponent extends Object { public $name="CkdComponent"; public
相关阅读排行
- 1ASP.NET 移动控件模板集和模板化控件
- 2使用FLASH控件实现SWF2JPG
- 3ASP.NET - ImageMap Web 服务器控件概述(二)
- 4【Visual Studio风格开发系列 - Form 工具】如何为控件提供工具箱位图
- 5iOS开发之如何获取各种控件的输入值
用户评论

游客