react-native-komect-uikit
Version:
React Native UI Toolkit
185 lines (155 loc) • 4.64 kB
JavaScript
/**
* @Author: will
* @Date: 2017-06-19T17:49:44+08:00
* @Filename: SwipeTouchableOpacity.js
* @Last modified by: will
* @Last modified time: 2017-06-20T15:05:44+08:00
*/
// SwipeTouchableOpacity.js
'use strict';
import React, {Component, PropTypes} from 'react';
import {StyleSheet, View, Text, TouchableOpacity, Animated} from 'react-native';
import Theme from '../themes/Theme';
export default class SwipeTouchableOpacity extends TouchableOpacity {
static propTypes = {
...TouchableOpacity.propTypes,
swipeable: PropTypes.bool,
swipeWidth: PropTypes.number,
onSwipeStsChange: PropTypes.func, //(swipeSts), - none, - moving, - closing, - opening, - opened
};
static defaultProps = {
...TouchableOpacity.defaultProps,
swipeable: true,
swipeWidth: 100,
};
constructor(props) {
super(props);
this._swipeSts = 'none';
this.translateX = 0;
this.prevTouches = [];
this.replaceSuperFunction();
Object.assign(this.state, {
translateX: new Animated.Value(0),
});
}
get swipeSts() {
return this._swipeSts;
}
set swipeSts(value) {
this._swipeSts = value;
this.props.onSwipeStsChange && this.props.onSwipeStsChange(this._swipeSts);
}
replaceSuperFunction() {
let touchableHandleResponderMove = this.touchableHandleResponderMove;
this.touchableHandleResponderMove = (e) => {
touchableHandleResponderMove(e);
this.swiping(e);
}
let touchableHandleActivePressOut = this.touchableHandleActivePressOut;
this.touchableHandleActivePressOut = (e) => {
this.swipeOver();
touchableHandleActivePressOut(e);
}
let touchableHandlePress = this.touchableHandlePress;
this.touchableHandlePress = (e) => {
if (!this.checkPress()) touchableHandlePress(e);
}
let touchableHandleLongPress = this.touchableHandleLongPress;
this.touchableHandleLongPress = (e) => {
if (!this.checkPress()) touchableHandleLongPress(e);
}
}
swiping(e) {
if (!this.props.swipeable || this.swipeSts === 'opened') {
return;
}
let {touches} = e.nativeEvent;
let prevTouches = this.prevTouches;
this.prevTouches = touches;
if (touches.length == 0 || touches.length != prevTouches.length) {
return;
}
for (let i = 0; i < touches.length; ++i) {
if (touches[i].identifier != prevTouches[i].identifier) {
return;
}
}
let dx = touches[0].pageX - prevTouches[0].pageX;
if (Math.abs(this.translateX) > this.props.swipeWidth){
this.translateX += dx / 3;
} else {
this.translateX += dx;
}
if (this.translateX > 16) {
this.translateX = 16;
}
if (this.swipeSts === 'moving') {
this.state.translateX.setValue(this.translateX);
} else if (Math.abs(this.translateX) > 5) {
let childStyle = StyleSheet.flatten(this.props.style) || {};
this.state.anim.setValue(childStyle.opacity === undefined ? 1 : childStyle.opacity); //TouchableOpacity
this.state.translateX.setValue(this.translateX);
this.swipeSts = 'moving';
}
}
swipeOver() {
this.prevTouches = [];
if (this.swipeSts === 'moving') {
if (this.translateX > 0) {
this.springClose();
} else if (-this.translateX > 40 || -this.translateX > this.props.swipeWidth / 2) {
this.timingOpen();
} else {
this.timingClose();
}
}
}
checkPress() {
if (this.swipeSts === 'opened') {
this.timingClose();
}
return this.swipeSts !== 'none';
}
springClose() {
this.swipeSts = 'closing';
this.translateX = 0;
Animated.spring(this.state.translateX, {
toValue: this.translateX,
friction: 5,
useNativeDriver: true,
}).start(() => {
this.swipeSts = 'none';
});
}
timingClose() {
this.swipeSts = 'closing';
this.translateX = 0;
Animated.timing(this.state.translateX, {
toValue: this.translateX,
duration: 150,
useNativeDriver: true,
}).start(() => {
this.swipeSts = 'none';
});
}
timingOpen() {
this.swipeSts = 'opening';
this.translateX = -this.props.swipeWidth;
Animated.timing(this.state.translateX, {
toValue: this.translateX,
duration: 150,
useNativeDriver: true,
}).start(() => {
this.swipeSts = 'opened';
});
}
buildProps() {
let {style, ...others} = this.props;
style = [].concat(style).concat({transform: [{translateX: this.state.translateX}]});
this.props = {style, ...others};
}
render() {
this.buildProps();
return super.render();
}
}