import React, {Component, ReactNode} from 'react' import {Animated, View, Modal, StyleSheet, TouchableOpacity, NativeEventSubscription} from 'react-native' import SystemTool from '../tool/SystemTool' import TimerTool from '../tool/TimerTool' import {isFunction} from '../tool/TypeTool' type StateType = { isShow: boolean } type PropsType = { onDismiss?: () => void customView: ReactNode viewHeight: number } export default class PYSheet extends Component { translateValue: Animated.Value opacityValue: Animated.Value backEvent: NativeEventSubscription | null = null constructor(props: PropsType) { super(props) this.translateValue = new Animated.Value(props.viewHeight) this.opacityValue = new Animated.Value(0) this.state = { isShow: false, } } componentDidMount() { this.backEvent = SystemTool.addBackListener(this._handleHwBackEvent.bind(this)) } componentWillUnmount() { this.backEvent && this.backEvent.remove() this.backEvent = null this.setState = () => {} } show = () => { this.setState({ isShow: true, }) Animated.parallel([ Animated.timing(this.translateValue, { toValue: 0, duration: 250, useNativeDriver: true, }), Animated.timing(this.opacityValue, { toValue: 1, duration: 250, useNativeDriver: true, }), ]).start() } hide = async (completion?: () => void) => { if (this.state.isShow) { Animated.parallel([ Animated.timing(this.translateValue, { toValue: this.props.viewHeight, duration: 250, useNativeDriver: true, }), Animated.timing(this.opacityValue, { toValue: 0, duration: 150, useNativeDriver: true, }), ]).start() isFunction(this.props.onDismiss) && this.props.onDismiss!() await TimerTool.delay(150) this.setState( { isShow: false, }, completion, ) } } _handleHwBackEvent = () => { this.hide() return true } render() { if (!this.state.isShow) { return null } return ( { this.hide() }}> {this.props.customView} ) } _onPressOutside = () => { this.hide() } } const styles = StyleSheet.create({ container: { width: '100%', height: '100%', alignItems: 'center', position: 'absolute', }, shadow: { width: '100%', height: '100%', position: 'absolute', backgroundColor: 'rgba(52,52,52,0.5)', }, contentContainer: { position: 'absolute', bottom: 0, width: '100%', alignItems: 'center', }, })