forked from ptomasroos/react-native-scrollable-tab-view
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
123 lines (103 loc) · 3.62 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
'use strict';
var React = require('react-native');
var {
Dimensions,
Text,
View,
TouchableOpacity,
PanResponder,
Animated,
} = React;
var DefaultTabBar = require('./DefaultTabBar');
var deviceWidth = Dimensions.get('window').width;
var ScrollableTabView = React.createClass({
getDefaultProps() {
return {
edgeHitWidth: 30,
}
},
getInitialState() {
return { currentPage: 0, scrollValue: new Animated.Value(0) };
},
componentWillMount() {
var release = (e, gestureState) => {
var relativeGestureDistance = gestureState.dx / deviceWidth,
lastPageIndex = this.props.children.length - 1,
vx = gestureState.vx,
newPage = this.state.currentPage;
if (relativeGestureDistance < -0.5 || (relativeGestureDistance < 0 && vx <= 0.5)) {
newPage = newPage + 1;
} else if (relativeGestureDistance > 0.5 || (relativeGestureDistance > 0 && vx >= 0.5)) {
newPage = newPage - 1;
}
this.props.hasTouch && this.props.hasTouch(false);
this.goToPage(Math.max(0, Math.min(newPage, this.props.children.length - 1)));
}
this._panResponder = PanResponder.create({
// Claim responder if it's a horizontal pan
onMoveShouldSetPanResponder: (e, gestureState) => {
if (Math.abs(gestureState.dx) > Math.abs(gestureState.dy)) {
if ((gestureState.moveX <= this.props.edgeHitWidth ||
gestureState.moveX >= deviceWidth - this.props.edgeHitWidth) &&
this.props.locked !== true) {
this.props.hasTouch && this.props.hasTouch(true);
return true;
}
}
},
// Touch is released, scroll to the one that you're closest to
onPanResponderRelease: release,
onPanResponderTerminate: release,
// Dragging, move the view with the touch
onPanResponderMove: (e, gestureState) => {
var dx = gestureState.dx;
var lastPageIndex = this.props.children.length - 1;
// This is awkward because when we are scrolling we are offsetting the underlying view
// to the left (-x)
var offsetX = dx - (this.state.currentPage * deviceWidth);
this.state.scrollValue.setValue(-1 * offsetX / deviceWidth);
},
});
},
goToPage(pageNumber) {
this.props.onChangeTab && this.props.onChangeTab({
i: pageNumber, ref: this.props.children[pageNumber]
});
this.setState({
currentPage: pageNumber
});
Animated.spring(this.state.scrollValue, {toValue: pageNumber, friction: 10, tension: 50}).start();
},
renderTabBar(props) {
if (this.props.renderTabBar === false) {
return null;
} else if (this.props.renderTabBar) {
return React.cloneElement(this.props.renderTabBar(), props);
} else {
return <DefaultTabBar {...props} />;
}
},
render() {
var sceneContainerStyle = {
width: deviceWidth * this.props.children.length,
flex: 1,
flexDirection: 'row'
};
var translateX = this.state.scrollValue.interpolate({
inputRange: [0, 1], outputRange: [0, -deviceWidth]
});
return (
<View style={{flex: 1}}>
{this.renderTabBar({goToPage: this.goToPage,
tabs: this.props.children.map((child) => child.props.tabLabel),
activeTab: this.state.currentPage,
scrollValue: this.state.scrollValue})}
<Animated.View style={[sceneContainerStyle, {transform: [{translateX}]}]}
{...this._panResponder.panHandlers}>
{this.props.children}
</Animated.View>
</View>
);
}
});
module.exports = ScrollableTabView;