class ssss extends Component {
constructor(props) {
super(props);
this.state = {
position: new Animated.Value(props.isOpen ? 0 : height),
opacity: new Animated.Value(0),
height: defaultHeight,
expanded: false,
visible: props.isOpen
};
}
// When user starts pulling popup previous height gets stored here
// to help us calculate new height value during and after pulling
_previousHeight = 0;
componentDidMount() {
// Initialize PanResponder to handle move gestures
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => {
const { dx, dy } = gestureState;
// Ignore taps
if (dx !== 0 && dy === 0) {
return true;
}
return false;
},
onPanResponderGrant: (evt, gestureState) => {
// Store previous height before user changed it
this._previousHeight = this.state.height;
},
onPanResponderMove: (evt, gestureState) => {
// Pull delta and velocity values for y axis from gestureState
const { dy, vy } = gestureState;
// Subtract delta y from previous height to get new height
let newHeight = this._previousHeight - dy;
// Animate heigh change so it looks smooth
LayoutAnimation.easeInEaseOut();
// Switch to expanded mode if popup pulled up above 80% mark
if (newHeight > 600 - 600 / 5) {
this.setState({ expanded: true });
} else {
this.setState({ expanded: false });
}
// Expand to full height if pulled up rapidly
if (vy < -0.75) {
this.setState({
expanded: true,
height: height * 0.65
});
}
// Close if pulled down rapidly
else if (vy > 0.75) {
this.props.onClose();
}
// Close if pulled below 95% mark of default height
else if (newHeight < defaultHeight * 0.95) {
this.props.onClose();
}
// Limit max height to screen height
else if (newHeight > 600) {
this.setState({ height: height * 0.65 });
} else {
this.setState({ height: newHeight });
}
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
const { dy } = gestureState;
const newHeight = this._previousHeight - dy;
// Close if pulled below default height
if (newHeight < defaultHeight) {
this.props.onClose();
}
// Update previous height
this._previousHeight = this.state.height;
},
onShouldBlockNativeResponder: (evt, gestureState) => {
// Returns whether this component should block native components from becoming the JS
// responder. Returns true by default. Is currently only supported on android.
return true;
}
});
}
// Handle isOpen changes to either open or close popup
componentWillReceiveProps(nextProps) {
// isOpen prop changed to true from false
if (!this.props.isOpen && nextProps.isOpen) {
this.animateOpen();
}
// isOpen prop changed to false from true
else if (this.props.isOpen && !nextProps.isOpen) {
this.animateClose();
}
}
// Open popup
animateOpen() {
// Update state first
this.setState({ visible: true }, () => {
Animated.parallel([
// Animate opacity
Animated.timing(
this.state.opacity,
{ toValue: 0.5 } // semi-transparent
),
// And slide up
Animated.timing(
this.state.position,
{ toValue: 0 } // top of the screen
)
]).start();
});
}
// Close popup
animateClose() {
Animated.parallel([
// Animate opacity
Animated.timing(
this.state.opacity,
{ toValue: 0 } // transparent
),
// Slide down
Animated.timing(
this.state.position,
{ toValue: height } // bottom of the screen
)
]).start(() =>
this.setState({
// Reset to default values
height: defaultHeight,
expanded: false,
visible: false
})
);
}
render() {
// Render nothing if not visible
if (!this.state.visible) {
return null;
}
return (
<View style={styles.container}>
{/* Closes popup if user taps on semi-transparent backdrop */}
<TouchableWithoutFeedback onPress={this.props.onClose}>
<Animated.View
style={[styles.backdrop, { opacity: this.state.opacity }]}
/>
</TouchableWithoutFeedback>
<Animated.View
style={[
styles.modal,
{
// Animates height
height: this.state.height,
// Animates position on the screen
transform: [
{ translateY: this.state.position },
{ translateX: 0 }
]
}
]}
>
{/* Content */}
<View style={styles.content}>
<View
style={[styles.topUpContainer]}
{...this._panResponder.panHandlers}
>
<View style={styles.hookerContainer}>
<View style={styles.hooker} />
</View>
{/* Your content comes here */}
</View>
</View>
</Animated.View>
</View>
);
}
}
Это может помочь вам