React Native 自定义实现【Toast】提示框

来源:互联网 发布:腾讯网络加速器独立版 编辑:程序博客网 时间:2024/06/05 12:47

今天和大家分享一篇自定义View的内容。


一、简介


之前和大家分享的自定义View内容,我们知道自定义View一般分为三个步骤:


(1)定义属性、状态

(2)定义组件行为

(3)绘制布局

(4)定义样式


二、分析


App中的提示(Toast)想必大家都不陌生,RN中也提供了ToastAndroid,但是由于仅能在Android平台使用,所以出现了很多开源的三方依赖库,例如react-native-root-toast等等。那么这种该如何实现呢?

1、Toast提示框大致由三部分组成:

(1)显示文字

(2)显示时长

(3)显示位置

(4)背景

我们可以根据这些来定义基本属性。


2、Toast的的状态分为两种:

(1)显示

(2)隐藏

显示/隐藏的行为我们可以通过state状态来控制。


3、在Toast显示隐藏时,可以用透明度动画来增加用户体验

分析了以上思路,那么就是撸码的节奏了。


三、实现


(1)定义属性、状态:

    // 定义props    static propTypes = {        textStyle: ViewPropTypes.style,        contentStyle: ViewPropTypes.style,        containerStyle: ViewPropTypes.style,        position: PropTypes.oneOf([            'top',            'center',            'bottom'        ])    }    //初始化 默认 props    static defaultProps = {        position: 'center'    }    constructor(props) {        super(props);        this.state = {            text: '',            isShow: false,            opacityAnimate: new Animated.Value(OPACITY) // 动画 值初始化        };        // 当前显示状态        this.isShow = false;         // 初始化默认显示时长为SHORT        this.duration = DURATION.SHORT;    }
(2)定义组件行为

   /**     * 显示     */    show(text, duration) {        if(duration >= DURATION.LONG) {            this.duration = DURATION.LONG;        } else {            this.duration = DURATION.SHORT;        }        // 显示        this.setState({            text: text,            isShow: true        });        this.isShow = true;        this.state.opacityAnimate.setValue(OPACITY);        // 执行隐藏操作        this.hide();    }    /**     * 隐藏     */    hide() {        // 隐藏状态下不执行操作        if(!this.isShow) {            return;        }        this.animateTimer && clearTimeout(this.animateTimer);        this.animateTimer = setTimeout(()=>{            // 开启动画            Animated.timing(                this.state.opacityAnimate,                {                    toValue: 0.0,                    duration: 600                }            ).start(()=>{                // 动画结束后,初始化状态                this.setState({                    isShow: false                })                this.isShow = false;            })        }, this.duration);    }
(3)绘制布局

    render() {        let top;        switch(this.props.position){            case 'top':                top = 30;                 break;            case 'center':                top = height / 2;                 break;            case 'bottom':                top = height - 100;                 break;            default:                break;        }        return this.state.isShow ?        <View             pointerEvents={ 'none' }            style={[ styles.container, { top: top } ]}>            <Animated.View                style={[ styles.content, this.props.contentStyle, { opacity: this.state.opacityAnimate } ]}                >                <Text style={[ styles.text, this.props.textStyle ]}>                    { this.state.text }                </Text>            </Animated.View>        </View> : null;    }}
(4)定义样式(建议单独封装样式,在组件中引用,遵循模块化开发)

const styles = StyleSheet.create({    container: {        position: 'absolute',        left: 0,        right: 0,        alignItems: 'center'    },    content: {        backgroundColor: '#000000',        opacity: OPACITY,        borderRadius: 20,        padding: 10    },    text: {        color: '#FFFFFF',        fontSize: 14,        fontFamily: 'PingFang-SC-Regular'    }})
以上代码很简单,基本使用了Animated + View 的方式来实现。最后贴上完整代码:

/** * Toast 提示 */import React, { Component, PropTypes } from 'react';import {    View,    Text,    Animated,    Dimensions,    StyleSheet,    ViewPropTypes} from 'react-native';// 设备屏幕宽高const { width, height } = Dimensions.get('window');// Toast提示框透明度const OPACITY = 0.8;// 显示时长export const DURATION = { LONG: 1500, SHORT: 500 };export default class Toast extends Component {    // 定义props    static propTypes = {        textStyle: ViewPropTypes.style,        contentStyle: ViewPropTypes.style,        containerStyle: ViewPropTypes.style,        position: PropTypes.oneOf([            'top',            'center',            'bottom'        ])    }    //初始化 默认 props    static defaultProps = {        position: 'center'    }    constructor(props) {        super(props);        this.state = {            text: '',            isShow: false,            opacityAnimate: new Animated.Value(OPACITY) // 动画 值初始化        };        // 当前显示状态        this.isShow = false;         // 初始化默认显示时长为SHORT        this.duration = DURATION.SHORT;    }    componentWillUnmount() {        // 在页面生命周期结束时,解除定时器,避免内存泄漏        this.animateTimer && clearTimeout(this.animateTimer);    }    /**     * 显示     */    show(text, duration) {        if(duration >= DURATION.LONG) {            this.duration = DURATION.LONG;        } else {            this.duration = DURATION.SHORT;        }        // 显示        this.setState({            text: text,            isShow: true        });        this.isShow = true;        this.state.opacityAnimate.setValue(OPACITY);        // 执行隐藏操作        this.hide();    }    /**     * 隐藏     */    hide() {        // 隐藏状态下不执行操作        if(!this.isShow) {            return;        }        this.animateTimer && clearTimeout(this.animateTimer);        this.animateTimer = setTimeout(()=>{            // 开启动画            Animated.timing(                this.state.opacityAnimate,                {                    toValue: 0.0,                    duration: 600                }            ).start(()=>{                // 动画结束后,初始化状态                this.setState({                    isShow: false                })                this.isShow = false;            })        }, this.duration);    }    render() {        let top;        switch(this.props.position){            case 'top':                top = 30;                 break;            case 'center':                top = height / 2;                 break;            case 'bottom':                top = height - 100;                 break;            default:                break;        }        return this.state.isShow ?        <View             pointerEvents={ 'none' }            style={[ styles.container, { top: top } ]}>            <Animated.View                style={[ styles.content, this.props.contentStyle, { opacity: this.state.opacityAnimate } ]}                >                <Text style={[ styles.text, this.props.textStyle ]}>                    { this.state.text }                </Text>            </Animated.View>        </View> : null;    }}const styles = StyleSheet.create({    container: {        position: 'absolute',        left: 0,        right: 0,        alignItems: 'center'    },    content: {        backgroundColor: '#000000',        opacity: OPACITY,        borderRadius: 20,        padding: 10    },    text: {        color: '#FFFFFF',        fontSize: 14,        fontFamily: 'PingFang-SC-Regular'    }})


四、使用


1、导入

import Toast from './components/Toast';<Toast ref="toast" position={'bottom'} />

2、调用:

  /**   * 显示   */  showToast() {     this.refs.toast.show('中奖了...', 1200);  }






原创粉丝点击