React-Native Toast

作者: 精神病患者link常 | 来源:发表于2018-11-01 17:12 被阅读23次

    源码地址: https://github.com/chjwrr/RN-Toast

    image.png image.png
    import React, {PureComponent} from 'react';
    import {
        Animated
    } from 'react-native'
    import Render from './render'
    import PropTypes from 'prop-types'
    
    export default class Toast extends PureComponent {
    
        constructor(props) {
            super(props);
    
            this.state = {
                isShow: false,
                opacityValue: new Animated.Value(0),
                text: this.props.text,
                image: this.props.image
            };
    
            this.showState = false; // 多次弹框情况下,确保弹出动画只走一次
    
            this.show = this.show.bind(this);
            this.close = this.close.bind(this)
            this.showImage = this.showImage.bind(this)
            this.showText = this.showText.bind(this)
    
            console.log('Toast constructor')
        };
        componentWillUnmount(){
            this.timer && clearTimeout(this.timer);
        }
        componentDidMount(){
            if (this.props.showType === 'api'){
                console.log('api方式调用')
                this.show()
            }else {
                console.log('组件方式调用')
            }
    
        }
        componentWillReceiveProps(nextProps){
            this.setState({
                text: nextProps.text,
                image: nextProps.image
            },()=>{
                this.show()
            });
        }
    
        // 组件方式
        showText(text, onDismiss){
            this.onDismiss = onDismiss
            this.setState({
                text
            },()=>{
                this.show()
            });
        }
    
        // 组件方式
        showImage(text, image, onDismiss){
            this.onDismiss = onDismiss
            this.setState({
                text,
                image
            },()=>{
                this.show()
            });
        }
    
        show(){
            this.setState({
                isShow: true,
            });
    
            // 重置计时器
            this.timer && clearTimeout(this.timer);
    
            if(this.showState){
                this.close();
                return
            }
    
            Animated.timing(
                this.state.opacityValue,
                {
                    toValue: 1,
                    duration: this.props.duration,
                }
            ).start(()=>{
    
                this.close();
                this.showState = true
            })
        }
    
        close(){
    
            this.timer = setTimeout(()=>{
                Animated.timing(
                    this.state.opacityValue,
                    {
                        toValue: 0,
                        duration: this.props.duration,
                    }
                ).start(()=>{
    
                    this.setState({
                        isShow: false
                    },()=>{
                        this.showState = false;
                        if (typeof this.props.onDismiss === 'function'){
                            this.props.onDismiss()
                        }
                        if (typeof this.onDismiss === 'function'){
                            this.onDismiss()
                        }
                    })
                })
            },this.props.delay)
        }
    
       render() {
    
            console.log('Toast render text==',this.state.text)
            let showImage = undefined // 无图片
    
            if (this.state.image === 'success'){
                showImage = successImage
            }
            if (this.state.image === 'warning'){
                showImage = warningImage
            }
            if (this.state.image === 'error'){
                showImage = errorImage
            }
            if (this.state.image === 'problem'){
                showImage = problemImage
            }
    
    
            const view = this.state.isShow ? <View style={[styles.container, this.props.viewStyle]} pointerEvents={'none'}>
                <Animated.View style={[styles.centerView, { opacity: this.state.opacityValue }]}>
                    {showImage && <Image style={styles.image} source={showImage}/>}
                    <Text style={[styles.text, this.props.textStyle]}>{this.state.text}</Text>
                </Animated.View>
            </View> : <View/>
    
            return view
        }
    }
    Toast.propsType = {
        text: PropTypes.string, // 标题
        image:PropTypes.oneOf(['success','warning','error','problem']), // 图片
        duration: PropTypes.number, // 动画效果持续时间
        delay:PropTypes.number, // toast 显示时间
        textStyle: PropTypes.object, // 自定义文本 style
        viewStyle: PropTypes.object, // 自定义view style
        onDismiss: PropTypes.func,
        showType: PropTypes.oneOf(['api','component']), // warning:调用方式,外界无需操作此参数 (api方式、组件方式)
    };
    Toast.defaultProps = {
        text: '',
        image: '',
        duration: 250,
        delay: 3000,
        showType: 'component'
    };
    
    
    import React from 'react';
    import {
        StyleSheet,
        Dimensions,
    } from 'react-native';
    
    import {whiteColor, blackColor} from './constValue/colorValue'
    const {width, height} = Dimensions.get('window');
    
    export default StyleSheet.create({
    
        container: {
            position: 'absolute',
            left: 0,
            top: 0,
            width,
            height,
            justifyContent: 'center',
            alignItems: 'center'
        },
        centerView: {
            backgroundColor: blackColor,
            borderRadius: 4,
            maxWidth: width * 2 / 3,
            paddingVertical: 10,
            paddingHorizontal: 25,
            justifyContent: 'center',
            alignItems: 'center'
        },
        text: {
            fontSize: 16,
            color: whiteColor,
            textAlign: 'center'
        },
        image: {
            width: 36,
            height: 36,
            marginBottom: 10
        }
    })
    

    调用方法一:组件的方式调用

    在视图的最外层View的最外面

    <Toast ref={'Toast'}/>
    

    需要的时候调用

    // 组件方式调用
            this.refs.Toast.showText('标题',()=>{
                console.log('组件方式调用 Toast text dismiss')
            })
            this.refs.Toast.showImage('标题', 'success', ()=>{
                console.log('组件方式调用 Toast image dismiss')
            })
    
    

    调用方法二:API方式调用,需要依赖react-native-root-siblings

    新建Toast

    import React from 'react'
    
    import RootSiblings from 'react-native-root-siblings';
    import ToastView from '../Toast'
    
    let rootSiblings = undefined;
    
    // options = { ToastView 内部 propsTypes }
    showText = (text, options = {}, onDismiss) => {
    
        if(rootSiblings){
            rootSiblings.update(<ToastView text={text}
                                           {...options}
                                           showType={'api'}
                                           onDismiss={()=>{
                                               onDismiss && typeof onDismiss === 'function' && onDismiss()
                                               this.hide()
                                           }}/>);
        }else {
    
            rootSiblings = new RootSiblings(<ToastView text={text}
                                                       {...options}
                                                       showType={'api'}
                                                       onDismiss={() => {
                                                           onDismiss && typeof onDismiss === 'function' && onDismiss()
                                                           this.hide()
                                                       }}/>)
        }
    };
    
    showImage = (text, image, options = {}, onDismiss) => {
        if(rootSiblings){
            rootSiblings.update(<ToastView text={text}
                                           image={image} {...options}
                                           showType={'api'}
                                           onDismiss={()=>{
                                               onDismiss && typeof onDismiss === 'function' && onDismiss()
                                               this.hide()
                                           }}/>)
        }else {
            rootSiblings = new RootSiblings(<ToastView text={text}
                                                       image={image}
                                                       {...options}
                                                       showType={'api'}
                                                       onDismiss={() => {
                                                           onDismiss && typeof onDismiss === 'function' && onDismiss()
                                                           this.hide()
                                                       }}/>);
        }
    };
    
    hide = () => {
        if (rootSiblings instanceof RootSiblings) {
            rootSiblings.destroy();
        } else {
            console.warn(`Toast.hide expected a \`RootSiblings\` instance as argument.\nBut got \`${typeof toast}\` instead.`);
        }
    };
    
    export default {
        showText,
        showImage
    };
    
    
    

    调用方式

     // API 方式调用
            Toast.showText('标题',()=>{})
            Toast.showImage('标题', 'success')
    

    相关文章

      网友评论

        本文标题:React-Native Toast

        本文链接:https://www.haomeiwen.com/subject/fvcztqtx.html