支持四个方向的抽屉效果,支持弹窗和全屏。
SlideView.tsx
import React, { Component, ReactElement, ReactNode } from 'react';
import { StyleSheet, Animated, Dimensions, ViewStyle } from 'react-native';
type ViewMode = 'fullscreen' | 'modal' | 'side';
type SlideTo = 'left' | 'top' | 'right' | 'bottom';
interface Props {
slideTo: SlideTo;
mode: ViewMode;
visible: boolean;
onDismiss: any;
children: ReactNode;
style: {zIndex?:number, elevation?:number};
modalBackdrop: ReactElement | null;
}
type Style = {
left: number;
top: number;
right: number;
bottom: number;
transform?: any;
};
const { width: winWidth, height: winHeight } = Dimensions.get('window');
export default class SlideView extends Component<Props> {
slideAnim: any;
startPosition = 0;
duration = 180;
style: Style = {
left: 0,
top: 0,
right: 0,
bottom: 0,
};
constructor(props: Props) {
super(props);
this.initSlide();
}
componentDidUpdate(prevProps: Props) {
if (this.props.visible !== prevProps.visible && this.props.visible === false) {
this.slideOut();
}
}
componentDidMount() {
this.slideIn();
}
slideIn = () => {
Animated.timing(
this.slideAnim,
{
toValue: 0,
duration: this.duration,
useNativeDriver: true,
}
).start();
};
slideOut = () => {
Animated.timing(
this.slideAnim,
{
toValue: this.startPosition,
duration: this.duration,
useNativeDriver: true,
}
).start(() => {
this.props.onDismiss();
});
};
initSlide() {
const sideMode = this.props.mode === 'side';
const to = this.props.slideTo;
const translateType = (to === 'left' || to === 'right')
? 'translateX'
: 'translateY';
let margin = 0;
let size = winWidth;
if (to == 'left' || to === 'right') {
if (sideMode) {
margin = Math.min(80, size * 0.2);
}
} else {
size = winHeight;
this.duration = 220;
if (sideMode) {
margin = Math.min(100, size * 0.2);
}
}
if (margin) {
size -= margin;
this.style[to] = margin;
}
this.startPosition = (to === 'right' || to === 'bottom') ? -size : size;
this.slideAnim = new Animated.Value(this.startPosition);
this.style.transform = [{ [translateType]: this.slideAnim }];
}
render() {
return (
<Animated.View style={[this.props.style, this.style]}>
{this.props.modalBackdrop}
{this.props.children}
</Animated.View>
)
}
}
const styles = StyleSheet.create({
});
example.tsx
<SlideView
visible={this.state.visible}
style={{zIndex:10,elevation:10}}
modalBackdrop={modalBackdrop}
onDismiss={this.props.onDismiss}
mode={this.mode}
slideTo={this.slideTo}
children={this.props.children} />