import React, { Component, ReactNode } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, StyleProp, TextStyle, ViewStyle, DeviceEventEmitter, EmitterSubscription, } from 'react-native'; import appStyles, { Theme } from '../styles'; import * as Animatable from 'react-native-animatable'; export interface PopupBtnProps { /** 按钮点击回调 */ onPress?: () => void; /** 按钮文字 */ title?: string; /** 按钮父控件样式 */ titleViewStyle?: StyleProp; /** 按钮文字样式 */ titleStyle?: StyleProp; } export interface PopupProps { /** 标题 */ title?: string; /** 标题父控件样式 */ titleViewStyle?: StyleProp; /** 标题文字样式 */ titleStyle?: StyleProp; /** 内容, 字符串文字或者字符串数组 */ content?: string | string[]; /** 内容父控件样式 */ contentViewStyle?: StyleProp; /** 内容文字样式 */ contentStyle?: StyleProp; /** 传入自定义内容区域控件 */ childView?: ReactNode; /** 右边确定按钮 */ okBtn?: PopupBtnProps; /** 左边取消按钮 */ cancelBtn?: PopupBtnProps; /** 是否一直保持显示不消失, 默认false */ keepShow?: boolean; /** alert窗体样式 */ style?: StyleProp; /** 背景样式 */ bgStyle?: StyleProp; /** 右边按钮默认样式 */ defaultOkBtnStyle?: StyleProp; /** 左边按钮默认样式 */ defaultCancelBtnStyle?: StyleProp; /** 右边按钮文字默认样式 */ defaultOkBtnTextStyle?: StyleProp; /** 左边按钮文字默认样式 */ defaultCancelBtnTextStyle?: StyleProp; /** 渐变显示小时时长, 默认250 */ fadeAnimTime?: number; } interface PopupState extends PopupProps { visible: boolean; [key: string]: any; } class Popup extends Component { showEmitter: EmitterSubscription; bgView: Animatable.View; static defaultProps = { keepShow: false, fadeAnimTime: 250, }; static show(popupConfig: PopupProps = {}) { DeviceEventEmitter.emit('POPUP_SHOW', popupConfig); } constructor(props) { super(props); this.state = { visible: false, title: null, titleViewStyle: null, titleStyle: null, content: null, contentViewStyle: null, contentStyle: null, childView: null, okBtn: null, cancelBtn: null, keepShow: false, style: null, bgStyle: null, defaultOkBtnStyle: null, defaultCancelBtnStyle: null, defaultOkBtnTextStyle: null, defaultCancelBtnTextStyle: null, ...props, }; } componentDidMount() { this.showEmitter = DeviceEventEmitter.addListener('POPUP_SHOW', (data: PopupProps = {}) => { this.setState({ ...data, visible: true }, () => { this.bgView.fadeIn(); }); }); } componentWillUnmount() { if (this.showEmitter) this.showEmitter.remove(); } _close = () => { this.bgView.fadeOut(); setTimeout(() => { this.setState({ visible: false, title: null, titleViewStyle: null, titleStyle: null, content: null, contentViewStyle: null, contentStyle: null, childView: null, okBtn: null, cancelBtn: null, keepShow: null, style: null, bgStyle: null, defaultOkBtnStyle: null, defaultCancelBtnStyle: null, defaultOkBtnTextStyle: null, defaultCancelBtnTextStyle: null, ...this.props, }); }, this.props.fadeAnimTime + 50); } _okOnPress = () => { const { okBtn, keepShow } = this.state; if (!keepShow) this._close(); if (okBtn && okBtn.onPress && okBtn.onPress instanceof Function) { okBtn.onPress(); } } _cancelOnPress = () => { const { cancelBtn, keepShow } = this.state; if (!keepShow) this._close(); if (cancelBtn && cancelBtn.onPress && cancelBtn.onPress instanceof Function) { cancelBtn.onPress(); } } _renderTitle = () => { const { title, content, titleViewStyle, titleStyle } = this.state; if (!title) return null; return ( {title} ); } _renderContent = () => { const { content, contentStyle, childView } = this.state; if (childView) { return childView; } else if (content) { return ( { Array.isArray(content) ? content.map((str, index) => ( {str} )) : {content} } ); } return null; } _renderButtons = () => { const { okBtn, cancelBtn, defaultOkBtnStyle, defaultCancelBtnStyle, defaultOkBtnTextStyle, defaultCancelBtnTextStyle, } = this.state; if (okBtn || cancelBtn) { return ( {cancelBtn ? : null} {okBtn ? : null} ); } else { return null; } } render() { if (!this.state.visible) return ; const { bgStyle, style, contentViewStyle, } = this.state; const { fadeAnimTime } = this.props; return ( this.bgView = r} easing={'ease-in-out'} style={[styles.container, bgStyle]} useNativeDriver> {this._renderTitle()} {this._renderContent()} {this._renderButtons()} ); } } const ButtonView = ({ onPress, title = '', style, textStyle }) => { return ( {title} ); }; const styles = StyleSheet.create({ container: { position: 'absolute', left: 0, top: 0, right: 0, bottom: 0, alignItems: 'center', justifyContent: 'center', backgroundColor: 'rgba(0,0,0,0.2)', } as ViewStyle, alert: { overflow: 'hidden', backgroundColor: Theme.white, width: px2dp(540), borderRadius: px2dp(20), } as ViewStyle, topView: { padding: px2dp(30), minHeight: px2dp(150), } as ViewStyle, title: { textAlign: 'center', fontWeight: 'bold', } as TextStyle, buttonsContainer: { flexDirection: 'row', minHeight: px2dp(90), } as ViewStyle, }); export default Popup;