源码地址: https://github.com/chjwrr/RN-Toast
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')
网友评论