|
2 | 2 | * Created by WittBulter on 16/9/5.
|
3 | 3 | */
|
4 | 4 |
|
5 |
| -import React, {Component} from 'react' |
6 |
| -import {StyleSheet, View, Text, Image, TouchableHighlight, Dimensions, Animated, Easing, Platform} from 'react-native' |
| 5 | +import React, { Component } from 'react' |
| 6 | +import { Animated, Dimensions, Easing, Image, Platform, StyleSheet, Text, TouchableHighlight, View } from 'react-native' |
7 | 7 | import Item from './item'
|
8 | 8 |
|
9 | 9 | export default class Tabbar extends Component {
|
10 |
| - |
11 |
| - static propTypes = { |
12 |
| - ...View.propTypes, |
13 |
| - style: View.propTypes.style, |
14 |
| - activeColor: React.PropTypes.string, |
15 |
| - height: React.PropTypes.number, |
16 |
| - } |
17 |
| - static Item = Item |
18 |
| - // 构造 |
19 |
| - constructor (props){ |
20 |
| - super(props) |
21 |
| - // 初始状态 |
22 |
| - this.state = { |
23 |
| - content: this.props.children, |
24 |
| - contentActive: this.props.index? this.props.index:0, |
25 |
| - contentHeight: this.props.height? this.props.height: 45, |
26 |
| - textActive: this.props.activeColor? this.props.activeColor: '#FE985B', |
27 |
| - footerMarginBottom: new Animated.Value(0), |
28 |
| - } |
29 |
| - } |
30 |
| - |
31 |
| - |
32 |
| - /** |
33 |
| - * |
34 |
| - * @param children {Array} children pages footer |
35 |
| - */ |
36 |
| - footerBar (children){ |
37 |
| - /** |
38 |
| - * |
39 |
| - * @param done {function} item callback |
40 |
| - * @param index {number} onpress index |
41 |
| - */ |
42 |
| - const pressHandle = (done, index) =>{ |
43 |
| - this.setState({ |
44 |
| - contentActive: index |
45 |
| - }) |
46 |
| - done&& done() |
47 |
| - } |
48 |
| - |
49 |
| - const textBox = () =>{ |
50 |
| - } |
51 |
| - return children.map((item, index) =>{ |
52 |
| - const active = this.state.contentActive== index |
53 |
| - const selected = item.props.selectedIcon? item.props.selectedIcon: item.props.icon |
54 |
| - const box = (text, icon) =>{ |
55 |
| - if (!text){ |
56 |
| - return ( |
57 |
| - <View style={styles.box}> |
58 |
| - <Image source={active? selected: item.props.icon} |
59 |
| - style={styles.onlyIcon} |
60 |
| - {...item.props.iconStyle} |
61 |
| - /> |
62 |
| - </View> |
63 |
| - ) |
64 |
| - } |
65 |
| - if (!icon){ |
66 |
| - return ( |
67 |
| - <View style={styles.box}> |
68 |
| - <Text style={[styles.onlyText, active&& {color: this.state.textActive}, {...item.props.textStyle}]} |
69 |
| - > |
70 |
| - {text} |
71 |
| - </Text> |
72 |
| - </View> |
73 |
| - ) |
74 |
| - } |
75 |
| - return ( |
76 |
| - <View style={styles.box}> |
77 |
| - <Image source={icon} |
78 |
| - style={styles.icon} |
79 |
| - {...item.props.iconStyle} |
80 |
| - /> |
81 |
| - <Text style={[styles.text, active&& {color: this.state.textActive}, {...item.props.textStyle}]} |
82 |
| - > |
83 |
| - {text} |
84 |
| - </Text> |
85 |
| - </View> |
86 |
| - ) |
87 |
| - } |
88 |
| - return ( |
89 |
| - <TouchableHighlight key={`tabbar-item${index}`} |
90 |
| - style={styles.footerButton} |
91 |
| - onPress={() => pressHandle(item.props.onPress, index)} |
92 |
| - underlayColor={'transparent'} |
93 |
| - > |
94 |
| - {box(item.props.text, active? selected: item.props.icon)} |
95 |
| - </TouchableHighlight> |
96 |
| - ) |
97 |
| - }) |
98 |
| - } |
99 |
| - |
100 |
| - render (){ |
101 |
| - return ( |
102 |
| - <View style={styles.body}> |
103 |
| - <View style={styles.content}> |
104 |
| - {this.state.content[this.state.contentActive].props.children} |
105 |
| - </View> |
106 |
| - <Animated.View style={[styles.footer, {marginBottom: this.state.footerMarginBottom}, {height: this.state.contentHeight}]} |
107 |
| - {...this.props.style} |
108 |
| - > |
109 |
| - {this.footerBar(this.props.children)} |
110 |
| - </Animated.View> |
111 |
| - </View> |
112 |
| - ) |
113 |
| - } |
114 |
| - |
115 |
| - /** |
116 |
| - * |
117 |
| - * @param t [{bool}] footBar show&hide |
118 |
| - */ |
119 |
| - toggleBar (t = (this.state.footerMarginBottom._value == 0 )){ |
120 |
| - Animated.timing( |
121 |
| - this.state.footerMarginBottom,{ |
122 |
| - toValue: t? -85: 0, |
123 |
| - duration: 190, |
124 |
| - easing: Easing.linear |
125 |
| - } |
126 |
| - ).start() |
127 |
| - } |
128 |
| - |
129 |
| - /** |
130 |
| - * |
131 |
| - * @param index [{number}] screen index |
132 |
| - */ |
133 |
| - jumpToIndex (index){ |
134 |
| - this.setState({ |
135 |
| - contentActive: index |
136 |
| - }) |
137 |
| - } |
138 |
| - |
139 |
| - |
140 |
| - componentWillReceiveProps(nextProps) { |
141 |
| - if (nextProps.index != undefined) this.jumpToIndex(nextProps.index) |
142 |
| - if (nextProps.toggleBar != undefined) this.toggleBar(!nextProps.toggleBar) |
143 |
| - } |
144 |
| - |
| 10 | + |
| 11 | + static propTypes = { |
| 12 | + ...View.propTypes, |
| 13 | + style: View.propTypes.style, |
| 14 | + activeColor: React.PropTypes.string, |
| 15 | + height: React.PropTypes.number, |
| 16 | + } |
| 17 | + static Item = Item |
| 18 | + |
| 19 | + constructor(props) { |
| 20 | + super(props) |
| 21 | + this.state = { |
| 22 | + content: this.props.children, |
| 23 | + contentActive: this.props.index || 0, |
| 24 | + contentHeight: this.props.height || 45, |
| 25 | + textActive: this.props.activeColor ? this.props.activeColor : '#fe985b', |
| 26 | + footerMarginBottom: new Animated.Value(0), |
| 27 | + } |
| 28 | + } |
| 29 | + |
| 30 | + /** |
| 31 | + * |
| 32 | + * @param children {Array} children pages footer |
| 33 | + */ |
| 34 | + footerBar(children) { |
| 35 | + /** |
| 36 | + * |
| 37 | + * @param done {function} item callback |
| 38 | + * @param index {number} onpress index |
| 39 | + */ |
| 40 | + const pressHandle = (done, index) => { |
| 41 | + this.setState({ contentActive: index }) |
| 42 | + done && done() |
| 43 | + } |
| 44 | + const textBox = () => {} |
| 45 | + |
| 46 | + return children.map((item, index) => { |
| 47 | + const active = this.state.contentActive === index |
| 48 | + const selected = item.props.selectedIcon || item.props.icon |
| 49 | + const box = (text, icon) => { |
| 50 | + if (!text) { |
| 51 | + return ( |
| 52 | + <View style={styles.box}> |
| 53 | + <Image source={active ? selected : item.props.icon} |
| 54 | + style={styles.onlyIcon} |
| 55 | + {...item.props.iconStyle}/> |
| 56 | + </View> |
| 57 | + ) |
| 58 | + } |
| 59 | + if (!icon) { |
| 60 | + return ( |
| 61 | + <View style={styles.box}> |
| 62 | + <Text style={[styles.onlyText, active && { color: this.state.textActive }, { ...item.props.textStyle }]}> |
| 63 | + {text} |
| 64 | + </Text> |
| 65 | + </View> |
| 66 | + ) |
| 67 | + } |
| 68 | + return ( |
| 69 | + <View style={styles.box}> |
| 70 | + <Image source={icon} style={styles.icon} {...item.props.iconStyle}/> |
| 71 | + <Text style={[styles.text, active && { color: this.state.textActive }, { ...item.props.textStyle }]}> |
| 72 | + {text} |
| 73 | + </Text> |
| 74 | + </View> |
| 75 | + ) |
| 76 | + } |
| 77 | + return ( |
| 78 | + <TouchableHighlight key={`tabbar-item${index}`} style={styles.footerButton} |
| 79 | + onPress={() => pressHandle(item.props.onPress, index)} |
| 80 | + underlayColor={'transparent'}> |
| 81 | + {box(item.props.text, active ? selected : item.props.icon)} |
| 82 | + </TouchableHighlight> |
| 83 | + ) |
| 84 | + }) |
| 85 | + } |
| 86 | + |
| 87 | + render() { |
| 88 | + return ( |
| 89 | + <View style={styles.body}> |
| 90 | + <View style={styles.content}> |
| 91 | + {this.state.content[this.state.contentActive].props.children} |
| 92 | + </View> |
| 93 | + <Animated.View |
| 94 | + style={[styles.footer, { marginBottom: this.state.footerMarginBottom }, { height: this.state.contentHeight }]} |
| 95 | + {...this.props.style}> |
| 96 | + {this.footerBar(this.props.children)} |
| 97 | + </Animated.View> |
| 98 | + </View> |
| 99 | + ) |
| 100 | + } |
| 101 | + |
| 102 | + /** |
| 103 | + * |
| 104 | + * @param t [{bool}] footBar show&hide |
| 105 | + */ |
| 106 | + toggleBar(t = (this.state.footerMarginBottom._value === 0 )) { |
| 107 | + Animated.timing( |
| 108 | + this.state.footerMarginBottom, { |
| 109 | + toValue: t ? -85 : 0, |
| 110 | + duration: 190, |
| 111 | + easing: Easing.linear, |
| 112 | + }, |
| 113 | + ).start() |
| 114 | + } |
| 115 | + |
| 116 | + /** |
| 117 | + * |
| 118 | + * @param index [{number}] screen index |
| 119 | + */ |
| 120 | + jumpToIndex(index) { |
| 121 | + this.setState({ contentActive: index }) |
| 122 | + } |
| 123 | + |
| 124 | + |
| 125 | + componentWillReceiveProps(nextProps) { |
| 126 | + nextProps.index !== undefined && this.jumpToIndex(nextProps.index) |
| 127 | + nextProps.toggleBar !== undefined && this.toggleBar(!nextProps.toggleBar) |
| 128 | + } |
| 129 | + |
145 | 130 | }
|
146 |
| -const {width, height} = Dimensions.get('window') |
| 131 | +const { width, height } = Dimensions.get('window') |
147 | 132 | const styles = StyleSheet.create({
|
148 |
| - body: { |
149 |
| - flexGrow: 1, |
150 |
| - width: width, |
151 |
| - overflow: 'hidden', |
152 |
| - height: height, |
153 |
| - flexDirection: 'column' |
154 |
| - }, |
155 |
| - content: { |
156 |
| - flex: 1, |
157 |
| - }, |
158 |
| - box: { |
159 |
| - flex: 1, |
160 |
| - alignItems: 'center', |
161 |
| - justifyContent: 'center', |
162 |
| - }, |
163 |
| - footer: { |
164 |
| - width: width, |
165 |
| - flexDirection: 'row', |
166 |
| - backgroundColor: '#fff', |
167 |
| - borderTopWidth: 1, |
168 |
| - borderTopColor: '#E5E5E5', |
169 |
| - }, |
170 |
| - footerButton: { |
171 |
| - flex: 1, |
172 |
| - alignItems: 'center', |
173 |
| - justifyContent: 'center', |
174 |
| - paddingTop: 5, |
175 |
| - paddingBottom: 5, |
176 |
| - }, |
177 |
| - icon: { |
178 |
| - width: Platform.OS == 'ios'?22:18, |
179 |
| - height: Platform.OS == 'ios'?22:18, |
180 |
| - alignItems: 'center', |
181 |
| - }, |
182 |
| - onlyIcon: { |
183 |
| - width: 27, |
184 |
| - height: 27, |
185 |
| - alignItems: 'center', |
186 |
| - marginTop: 5, |
187 |
| - marginBottom: 5, |
188 |
| - }, |
189 |
| - text: { |
190 |
| - fontSize: 12, |
191 |
| - color: '#9B9DB0', |
192 |
| - paddingTop: 3, |
193 |
| - textAlign: 'center' |
194 |
| - }, |
195 |
| - onlyText: { |
196 |
| - fontSize: 16, |
197 |
| - color: '#9B9DB0', |
198 |
| - alignItems: 'center', |
199 |
| - justifyContent: 'center', |
200 |
| - marginTop: 8, |
201 |
| - marginBottom: 8, |
202 |
| - }, |
| 133 | + body: { |
| 134 | + flexGrow: 1, |
| 135 | + width: width, |
| 136 | + overflow: 'hidden', |
| 137 | + height: height, |
| 138 | + flexDirection: 'column', |
| 139 | + }, |
| 140 | + content: { |
| 141 | + flex: 1, |
| 142 | + }, |
| 143 | + box: { |
| 144 | + flex: 1, |
| 145 | + alignItems: 'center', |
| 146 | + justifyContent: 'center', |
| 147 | + }, |
| 148 | + footer: { |
| 149 | + width: width, |
| 150 | + flexDirection: 'row', |
| 151 | + backgroundColor: '#fff', |
| 152 | + borderTopWidth: 1, |
| 153 | + borderTopColor: '#e5e5e5', |
| 154 | + }, |
| 155 | + footerButton: { |
| 156 | + flex: 1, |
| 157 | + alignItems: 'center', |
| 158 | + justifyContent: 'center', |
| 159 | + paddingTop: 5, |
| 160 | + paddingBottom: 5, |
| 161 | + }, |
| 162 | + icon: { |
| 163 | + width: Platform.OS === 'ios' ? 22 : 18, |
| 164 | + height: Platform.OS === 'ios' ? 22 : 18, |
| 165 | + alignItems: 'center', |
| 166 | + }, |
| 167 | + onlyIcon: { |
| 168 | + width: 27, |
| 169 | + height: 27, |
| 170 | + alignItems: 'center', |
| 171 | + marginTop: 5, |
| 172 | + marginBottom: 5, |
| 173 | + }, |
| 174 | + text: { |
| 175 | + fontSize: 12, |
| 176 | + color: '#9b9db0', |
| 177 | + paddingTop: 3, |
| 178 | + textAlign: 'center', |
| 179 | + }, |
| 180 | + onlyText: { |
| 181 | + fontSize: 16, |
| 182 | + color: '#9b9db0', |
| 183 | + alignItems: 'center', |
| 184 | + justifyContent: 'center', |
| 185 | + marginTop: 8, |
| 186 | + marginBottom: 8, |
| 187 | + }, |
203 | 188 | })
|
0 commit comments