1 | import React, {
|
2 | PropTypes,
|
3 | Component,
|
4 | ViewPropTypes,
|
5 | ViewStylePropTypes,
|
6 | } from 'react';
|
7 | import {
|
8 | View,
|
9 | Text,
|
10 | Animated,
|
11 | Dimensions,
|
12 | StyleSheet,
|
13 | } from 'react-native';
|
14 | import DefaultTabBar from '../TabBar';
|
15 | import SceneComponent from './Scene';
|
16 |
|
17 |
|
18 | const styles = StyleSheet.create({
|
19 | container: {
|
20 | flex: 1,
|
21 | },
|
22 | activeTextStyle: {
|
23 | color: '#82A0FA',
|
24 | },
|
25 | tabDeafultText: {
|
26 | color: '#888',
|
27 | },
|
28 | tabBackground: {
|
29 | flex: 1,
|
30 | alignItems: 'center',
|
31 | justifyContent: 'center',
|
32 | paddingBottom: 10,
|
33 | },
|
34 | scrollContent: {
|
35 | flex: 1,
|
36 | flexDirection: 'row',
|
37 | },
|
38 | });
|
39 |
|
40 | class TabScene extends Component {
|
41 | static propTypes = {
|
42 | tabBarPosition: PropTypes.oneOf(['top', 'bottom', 'overlayTop', 'overlayBottom']),
|
43 | initialPage: PropTypes.number,
|
44 | page: PropTypes.number,
|
45 | onChangeTab: PropTypes.func,
|
46 | renderTabBar: PropTypes.func,
|
47 | activeTextStyle: Text.propTypes.style,
|
48 | defaultTextStyle: Text.propTypes.style,
|
49 | tabBarStyle: ViewStylePropTypes || (View.propTypes && View.propTypes.style),
|
50 | tabUnderLineStyle: ViewStylePropTypes || (View.propTypes && View.propTypes.style),
|
51 | children: PropTypes.array,
|
52 | }
|
53 | static defaultProps = {
|
54 | tabBarPosition: 'top',
|
55 | initialPage: 0,
|
56 | page: -1,
|
57 | onChangeTab: () => {},
|
58 | tabBarStyle: null,
|
59 | tabUnderLineStyle: null,
|
60 | defaultTextStyle: styles.defaultTextStyle,
|
61 | activeTextStyle: styles.activeTextStyle,
|
62 | style: null,
|
63 | renderTabBar: null,
|
64 | children: [],
|
65 | }
|
66 | constructor(props) {
|
67 | super(props);
|
68 | this.state = {
|
69 | currentPage: props.initialPage,
|
70 | containerWidth: Dimensions.get('window').width,
|
71 | fadeAnim: new Animated.Value(0),
|
72 | len: this.props.children.length,
|
73 | };
|
74 | }
|
75 | componentWillReceiveProps = (props) => {
|
76 | if (props.page >= 0 && props.page !== this.state.currentPage) {
|
77 | this.goToPage(props.page);
|
78 | }
|
79 | }
|
80 | _children = (children = this.props.children) => React.Children.map(children, child => child);
|
81 |
|
82 | goToScene = (pageNumber) => {
|
83 | const offset = pageNumber * this.state.containerWidth;
|
84 | const currentPage = this.state.currentPage;
|
85 | this.updateSceneKeys({
|
86 | page: pageNumber,
|
87 | callback: this._onChangeTab.bind(this, currentPage, pageNumber),
|
88 | });
|
89 | Animated.spring(
|
90 | this.state.fadeAnim,
|
91 | {
|
92 | toValue: -offset,
|
93 | },
|
94 | ).start();
|
95 | }
|
96 | updateSceneKeys = ({ page, children = this.props.children, callback = () => {} }) => {
|
97 | this.setState({ currentPage: page }, callback);
|
98 | }
|
99 |
|
100 | _onChangeTab = (prevPage, currentPage) => {
|
101 | this.props.onChangeTab({
|
102 | i: currentPage,
|
103 | ref: this._children()[currentPage],
|
104 | from: prevPage,
|
105 | });
|
106 | }
|
107 | renderScrollableContent = () => this._children().map((child, idx, children) => {
|
108 | const tabLabel = child.props.tabLabel;
|
109 | return (
|
110 | <SceneComponent
|
111 | key={child.key}
|
112 | style={child.props.style}
|
113 | >
|
114 | {child}
|
115 | </SceneComponent>
|
116 | );
|
117 | });
|
118 |
|
119 |
|
120 | renderTabBar = (props) => {
|
121 | if (this.props.renderTabBar === false) {
|
122 | return null;
|
123 | } else if (this.props.renderTabBar) {
|
124 | return React.cloneElement(this.props.renderTabBar(props), props);
|
125 | }
|
126 | return <DefaultTabBar {...props} style={{ height: 30 }} />;
|
127 | }
|
128 |
|
129 | get tabBarProps() {
|
130 | return {
|
131 | goToScene: this.goToScene,
|
132 | tabs: this._children().map(child => child.props.tabLabel),
|
133 | activeTab: this.state.currentPage,
|
134 | activeTextStyle: this.props.activeTextStyle,
|
135 | defaultTextStyle: this.props.defaultTextStyle,
|
136 | tabUnderLineStyle: this.props.tabUnderLineStyle,
|
137 | tabBarStyle: this.props.tabBarStyle,
|
138 | };
|
139 | }
|
140 |
|
141 | render() {
|
142 | return (
|
143 | <View style={styles.container}>
|
144 | {this.props.tabBarPosition === 'top' && this.renderTabBar(this.tabBarProps)}
|
145 | <View style={{ flex: 1, flexDirection: 'row', width: this.state.containerWidth * this.state.len }}>
|
146 | <Animated.View
|
147 | style={[styles.scrollContent, { width: this.state.containerWidth }, {
|
148 | transform: [
|
149 | { translateX: this.state.fadeAnim },
|
150 | ],
|
151 | }]}
|
152 | >
|
153 | {this.renderScrollableContent()}
|
154 | </Animated.View>
|
155 | </View>
|
156 | </View>
|
157 | );
|
158 | }
|
159 | }
|
160 | export default TabScene;
|
161 |
|
\ | No newline at end of file |