RN 项目使用组件ReactNative 自定义组件

React-Native Toast

2018-11-01  本文已影响23人  精神病患者link常

源码地址: 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')
上一篇 下一篇

猜你喜欢

热点阅读