rn-swipe-up-down
Version:
Swipe Up Down component with icon color
188 lines (174 loc) • 5.5 kB
JavaScript
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View,
PanResponder,
Dimensions,
LayoutAnimation,
TouchableOpacity
} from "react-native";
import SwipeIcon from "./components/SwipeIcon";
import images from "../../assets/images";
const MARGIN_TOP = Platform.OS === "ios" ? 20 : 0;
const DEVICE_HEIGHT = Dimensions.get("window").height - MARGIN_TOP;
export default class SwipeUpDown extends Component{
static defautProps = {
disablePressToShow: false,
iconColor: 'white'
};
constructor(props) {
super(props);
this.state = {
collapsed: true
};
this.disablePressToShow = props.disablePressToShow;
this.SWIPE_HEIGHT = props.swipeHeight || 60;
this._panResponder = null;
this.top = this.SWIPE_HEIGHT;
this.height = this.SWIPE_HEIGHT;
this.customStyle = {
style: {
bottom: 0,
top: this.top,
height: this.height
}
};
this.checkCollapsed = true;
this.showFull = this.showFull.bind(this);
}
componentWillMount() {
this._panResponder = PanResponder.create({
onMoveShouldSetPanResponder: (event, gestureState) => true,
onPanResponderMove: this._onPanResponderMove.bind(this),
onPanResponderRelease: this._onPanResponderRelease.bind(this)
});
}
componentDidMount() {
this.props.hasRef && this.props.hasRef(this);
}
updateNativeProps() {
switch (this.props.animation) {
case "linear":
LayoutAnimation.linear();
break;
case "spring":
LayoutAnimation.spring();
break;
case "easeInEaseOut":
LayoutAnimation.easeInEaseOut();
break;
case "none":
default:
break;
}
this.viewRef.setNativeProps(this.customStyle);
}
_onPanResponderMove(event, gestureState) {
if (gestureState.dy > 0 && !this.checkCollapsed) {
// SWIPE DOWN
this.customStyle.style.top = this.top + gestureState.dy;
this.customStyle.style.height = DEVICE_HEIGHT - gestureState.dy;
this.swipeIconRef && this.swipeIconRef.setState({ icon: this.props.iconColor === 'white' ? images.minus : images.minus_black });
!this.state.collapsed && this.setState({ collapsed: true });
this.updateNativeProps();
} else if (this.checkCollapsed && gestureState.dy < -60) {
// SWIPE UP
this.top = 0;
this.customStyle.style.top = DEVICE_HEIGHT + gestureState.dy;
this.customStyle.style.height = -gestureState.dy + this.SWIPE_HEIGHT;
this.swipeIconRef &&
this.swipeIconRef.setState({ icon: this.props.iconColor === 'white' ? images.minus : images.minus_black, showIcon: true });
if (this.customStyle.style.top <= DEVICE_HEIGHT / 2) {
this.swipeIconRef &&
this.swipeIconRef.setState({
icon: this.props.iconColor === 'white' ? images.arrow_down : images.arrow_down_black,
showIcon: true
});
}
this.updateNativeProps();
this.state.collapsed && this.setState({ collapsed: false });
}
}
_onPanResponderRelease(event, gestureState) {
if (gestureState.dy < -100 || gestureState.dy < 100) {
this.showFull();
} else {
this.showMini();
}
}
showFull() {
const { onShowFull } = this.props;
this.customStyle.style.top = 0;
this.customStyle.style.height = DEVICE_HEIGHT;
this.swipeIconRef &&
this.swipeIconRef.setState({ icon: this.props.iconColor === 'white' ? images.arrow_down : images.arrow_down_black, showIcon: true });
this.updateNativeProps();
this.state.collapsed && this.setState({ collapsed: false });
this.checkCollapsed = false;
onShowFull && onShowFull();
}
showMini() {
const { onShowMini, itemMini } = this.props;
this.SWIPE_HEIGHT = 150; //Avoid hiding when swiping down.
this.customStyle.style.top = itemMini
? DEVICE_HEIGHT - this.SWIPE_HEIGHT
: DEVICE_HEIGHT;
this.customStyle.style.height = itemMini ? this.SWIPE_HEIGHT : 0;
this.swipeIconRef && this.swipeIconRef.setState({ showIcon: false });
this.updateNativeProps();
!this.state.collapsed && this.setState({ collapsed: true });
this.checkCollapsed = true;
onShowMini && onShowMini();
}
render() {
const { itemMini, itemFull, style } = this.props;
const { collapsed } = this.state;
return (
<View
ref={ref => (this.viewRef = ref)}
{...this._panResponder.panHandlers}
style={[
styles.wrapSwipe,
{
height: this.SWIPE_HEIGHT,
marginTop: MARGIN_TOP
},
!itemMini && collapsed && { marginBottom: -200 },
style
]}
>
<SwipeIcon
onClose={() => this.showMini()}
hasRef={ref => (this.swipeIconRef = ref)}
/>
{collapsed ? (
itemMini ? (
<TouchableOpacity
activeOpacity={this.disablePressToShow ? 1 : 0.6}
style={{ height: this.SWIPE_HEIGHT }}
onPress={() => !this.disablePressToShow && this.showFull()}
>
{itemMini}
</TouchableOpacity>
) : null
) : (
itemFull
)}
</View>
);
}
}
const styles = StyleSheet.create({
wrapSwipe: {
padding: 10,
backgroundColor: "#ccc",
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
position: "absolute",
bottom: 0,
left: 0,
right: 0
}
});