|
| 1 | +# ReactNative短信验证码倒计时控件 |
| 2 | + |
| 3 | +## 功能 |
| 4 | + |
| 5 | +根据项目的需要,需要写一个自定义的控件,实现如下功能: |
| 6 | + |
| 7 | +- 默认文字为**点击获取验证码** |
| 8 | +- 点击后出现60秒的倒计时 |
| 9 | +- 颜色,字号可调 |
| 10 | +- 倒计时过程中,再次点击需要忽略掉 |
| 11 | +- 倒计时完成后文本恢复成**点击获取验证码** |
| 12 | +- 再几次点击同之前 |
| 13 | + |
| 14 | + |
| 15 | +其实说了这么多,就是个最普通的验证码的功能。。。 |
| 16 | + |
| 17 | +## 效果 |
| 18 | + |
| 19 | +效果图如下:(录的图片比较一般,对付着看吧) |
| 20 | + |
| 21 | + |
| 22 | + |
| 23 | +## 实现原理 |
| 24 | + |
| 25 | +自己封装了个控件,它内部含有一个Text控件,然后我们又写了一个timer,然后负责倒计时,然后每次都需要判断一下是否继续,然后加了一个flag字段,判断是否接受下次点击事件,当倒计时结束之后还需要将初始状态重置回去即可。 |
| 26 | + |
| 27 | +## 代码 |
| 28 | + |
| 29 | +### 控件代码 |
| 30 | + |
| 31 | +``` |
| 32 | +import React, {Component } from 'react'; |
| 33 | +import { |
| 34 | + StyleSheet, |
| 35 | + Text, |
| 36 | + View, |
| 37 | + Image, |
| 38 | + TextInput, |
| 39 | + TouchableHighlight, |
| 40 | + StatusBar, |
| 41 | + Alert, |
| 42 | + AppRegistry |
| 43 | +} from 'react-native'; |
| 44 | +import LinkRow from '../components/LinkRow'; |
| 45 | +import cStyles from '../styles/CommonStyle'; |
| 46 | +
|
| 47 | +import axios from 'axios'; |
| 48 | +
|
| 49 | +class MyCountTime extends Component { |
| 50 | + constructor(props) { |
| 51 | + super(props); |
| 52 | + let timeLeft = this.props.timeLeft > 0 ? this.props.timeLeft : 5; |
| 53 | + let width = this.props.width || 100; |
| 54 | + let height = this.props.height || 50; |
| 55 | + let color = this.props.color || '#42A5F5'; |
| 56 | + let fontSize = this.props.fontSize || 30; |
| 57 | + let fontWeight = this.props.fontWeight || '600'; |
| 58 | + let borderColor = this.props.borderColor || '#42A5F5'; |
| 59 | + let borderWidth = this.props.borderWidth || 1; |
| 60 | + let borderRadius = this.props.borderRadius || 4; |
| 61 | + let backgroundColor = this.props.backgroundColor || '#42A5F5'; |
| 62 | + let begin = 0; |
| 63 | + let press = this.props.press; |
| 64 | +
|
| 65 | + this.afterEnd = this.props.afterEnd || this._afterEnd; |
| 66 | + this.style = this.props.style; |
| 67 | +
|
| 68 | + this.state = { |
| 69 | + timeLeft: timeLeft, |
| 70 | + begin: begin |
| 71 | + }; |
| 72 | + this.countTextStyle = { |
| 73 | + textAlign: 'center', |
| 74 | + color: '#42A5F5', |
| 75 | + fontSize: fontSize, |
| 76 | + fontWeight: fontWeight |
| 77 | +
|
| 78 | + }; |
| 79 | + this.countViewStyle = { |
| 80 | + backgroundColor: backgroundColor, |
| 81 | + alignItems: 'center', |
| 82 | + borderColor: borderColor, |
| 83 | + borderWidth: borderWidth, |
| 84 | + borderRadius: borderRadius, |
| 85 | + width: width, |
| 86 | + height: height |
| 87 | + } |
| 88 | + } |
| 89 | +
|
| 90 | + countdownfn(timeLeft, callback, begin) { |
| 91 | + if (timeLeft > 0) { |
| 92 | + this.state.begin = 1; |
| 93 | + console.log("===lin===>"); |
| 94 | +
|
| 95 | + let that = this; |
| 96 | + let interval = setInterval(function () { |
| 97 | + if (that.state.timeLeft < 1) { |
| 98 | + clearInterval(interval); |
| 99 | + callback(that) |
| 100 | + } else { |
| 101 | + let totalTime = that.state.timeLeft; |
| 102 | + that.setState({ |
| 103 | + timeLeft: totalTime - 1 |
| 104 | + }) |
| 105 | + } |
| 106 | + }, 1000) |
| 107 | + } |
| 108 | + } |
| 109 | +
|
| 110 | + _beginCountDown() { |
| 111 | + if (this.state.begin === 1){ |
| 112 | + return; |
| 113 | + } |
| 114 | + let time = this.state.timeLeft; |
| 115 | + console.log("===lin===> time " + time); |
| 116 | + let afterEnd = this.afterEnd; |
| 117 | + let begin = this.state.begin; |
| 118 | + console.log("===lin===> start " + begin); |
| 119 | + this.countdownfn(time, afterEnd, begin) |
| 120 | + } |
| 121 | +
|
| 122 | + _afterEnd(that) { |
| 123 | + console.log('------------time over'); |
| 124 | + that.setState({ |
| 125 | + begin : 0, |
| 126 | + timeLeft : 5, |
| 127 | + }) |
| 128 | + } |
| 129 | +
|
| 130 | + componentDidMount() { |
| 131 | +
|
| 132 | + } |
| 133 | +
|
| 134 | + render() { |
| 135 | + return ( |
| 136 | + <View style={{position:'absolute',top:13,right:43,height:30}}> |
| 137 | + <Text |
| 138 | + onPress={this._beginCountDown.bind(this)} |
| 139 | + style={{color: '#42A5F5', fontSize: 17,height:40 , zIndex:999}}> { this.state.begin === 0 ? '点击获取验证码' : this.state.timeLeft} </Text> |
| 140 | +
|
| 141 | + </View> |
| 142 | + ) |
| 143 | + } |
| 144 | +} |
| 145 | +
|
| 146 | +``` |
| 147 | + |
| 148 | +### 应用代码 |
| 149 | + |
| 150 | +``` |
| 151 | +<MyCountTime timeLeft={5}> |
| 152 | +
|
| 153 | +</MyCountTime> |
| 154 | +
|
| 155 | +``` |
| 156 | + |
| 157 | + |
| 158 | +当然这只是,最简单的应用的代码,我们还提供了很多的自定义的属性,大家可以根据自己项目的需要,去调节这些参数。 |
| 159 | + |
| 160 | +---- |
| 161 | + |
| 162 | +由于最近刚开始认真的搞RN,可能有一些封装的不是最佳实践,还是希望大家多提意见,和大家一起进步吧。 |
| 163 | + |
| 164 | + |
0 commit comments