关闭

React Native 自定义控件之验证码和Toast

标签: androidios验证码native
4173人阅读 评论(4) 收藏 举报
分类:

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();
    }

完整代码:

/**
 * 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)=>{
 }}/>
2
0
查看评论

react native 获取验证码

获取验证码控件:https://github.com/781238222/react-native-verify-code
  • mengks1987
  • mengks1987
  • 2017-08-02 15:34
  • 1371

验证码插件 Demo

jquery插件 验证码 js
  • wx11408115
  • wx11408115
  • 2017-05-27 09:58
  • 263

react native Toast封装

app经常用到消息的提示功能,封装效果图: 样式我封装的只有2个样式,错误提示就像图中一样,红底,普通提示是黑底,如果需要求他样式请自行修改。封装代码:import React, {Component} from 'react'; import { StyleSheet...
  • mengks1987
  • mengks1987
  • 2017-07-07 09:58
  • 593

React Native 学习笔记十三(原生模块之Toast)

在学习官网上的Toast 的过程中 出现很多的坑  废话就不说了 官网上都有 官网讲解 实现思路 : 我们之前已经将react-native 嵌入原生了 那么 我们就在之前的基础上进行修改就好了    创建ToastUtils.java 继承React...
  • Youth_never_go_away
  • Youth_never_go_away
  • 2016-09-20 14:40
  • 1030

react native学习之Toast

今天学习react native中的另外一些API,在android开发中,经常会需要用到ToastAndroid,其实facebook也封装好了该组件,ToastAndroid。ToastAndroid学习先看下使用ToastAndroid的方法和属性方法 static show(message:...
  • mockingbirds
  • mockingbirds
  • 2016-01-19 23:51
  • 6127

react-native 添加 Toast 模块

1.创建一个原生模块开始。一个原生模块是一个通常继承 ReactContextBaseJavaModule 类的 Java 类,并且实现了 JavaScript 需要实现的方法 public class AliToastAndroid extends ReactContex...
  • q617610589
  • q617610589
  • 2015-10-27 16:10
  • 3236

react-native-easy-toast, 一款简单易用的 Toast 组件,支持 Android&iOS.

原文  https://github.com/crazycodeboy/react-native-easy-toast react-native-easy-toast A react native module to show toast like android...
  • sinat_17775997
  • sinat_17775997
  • 2017-03-07 22:28
  • 4438

React Js 精简 Toast 提示框 不使用jquery

本文出自: http://blog.csdn.net/wyk304443164 效果图:直接放代码,代码贼少。toast.js/** * Created by wuyakun on 2017/6/7. */import './toast.less';export let to...
  • wyk304443164
  • wyk304443164
  • 2017-06-07 09:58
  • 1667

React Native倒计时

在开发电商相关的APP的时候,经常会有秒杀,团购的倒计时的需求,跟大家推荐一个开源的倒计时组件: github地址:https://github.com/jackuhan/react-native-CountDowntimer 该组件只需要添加一个结束时间即可,非常方便,适用于商品秒杀页面等。 ...
  • chichengjunma
  • chichengjunma
  • 2017-03-28 09:50
  • 980

React-Native初体验五(window下引用第三方库:Toast)

在看这篇文章是居于reactNativeTest项目的,要是没有看过之前的文章请先看React-Native初体验四下面介绍的第三方库是:react-native-root-toast react-native-root-toast项目简介Features: Pure javascript sol...
  • u012987546
  • u012987546
  • 2016-09-21 14:09
  • 4572
    本人新书
    个人资料
    • 访问:2233167次
    • 积分:29438
    • 等级:
    • 排名:第208名
    • 原创:763篇
    • 转载:268篇
    • 译文:25篇
    • 评论:395条
    技术公众号
      欢迎关注我的公众号,每天为你推荐最新的博文,与大家一起学习共同进步!
    博客专栏
    站长统计
    微博
    最新评论
    本人新作

    新书