Authored by 于良

tab切换优化 review by 盖剑秋

@@ -59,6 +59,7 @@ const ScrollableTabView = React.createClass({ @@ -59,6 +59,7 @@ const ScrollableTabView = React.createClass({
59 getInitialState() { 59 getInitialState() {
60 return { 60 return {
61 currentPage: this.props.initialPage, 61 currentPage: this.props.initialPage,
  62 + currentPageContentHeight: 0,
62 scrollValue: new Animated.Value(this.props.initialPage), 63 scrollValue: new Animated.Value(this.props.initialPage),
63 containerWidth: Dimensions.get('window').width, 64 containerWidth: Dimensions.get('window').width,
64 sceneKeys: this.newSceneKeys({ currentPage: this.props.initialPage, }), 65 sceneKeys: this.newSceneKeys({ currentPage: this.props.initialPage, }),
@@ -110,7 +111,21 @@ const ScrollableTabView = React.createClass({ @@ -110,7 +111,21 @@ const ScrollableTabView = React.createClass({
110 111
111 updateSceneKeys({ page, children = this.props.children, callback = () => {}, }) { 112 updateSceneKeys({ page, children = this.props.children, callback = () => {}, }) {
112 let newKeys = this.newSceneKeys({ previousKeys: this.state.sceneKeys, currentPage: page, children, }); 113 let newKeys = this.newSceneKeys({ previousKeys: this.state.sceneKeys, currentPage: page, children, });
113 - this.setState({currentPage: page, sceneKeys: newKeys, }, callback); 114 +
  115 + let currentPageContentHeight = 0;
  116 + if (this.props.getCurrentPageHeight) {
  117 + let currentPageHeight = this.props.getCurrentPageHeight(page);
  118 + currentPageContentHeight = currentPageHeight;
  119 + // if (currentPageHeight > 0) {
  120 + // this.scrollView.setNativeProps({
  121 + // style: {
  122 + // height: currentPageHeight,
  123 + // },
  124 + // });
  125 + // }
  126 + }
  127 +
  128 + this.setState({currentPage: page, sceneKeys: newKeys, currentPageContentHeight: currentPageContentHeight}, callback);
114 }, 129 },
115 130
116 newSceneKeys({ previousKeys = [], currentPage = 0, children = this.props.children, }) { 131 newSceneKeys({ previousKeys = [], currentPage = 0, children = this.props.children, }) {
@@ -230,6 +245,7 @@ const ScrollableTabView = React.createClass({ @@ -230,6 +245,7 @@ const ScrollableTabView = React.createClass({
230 ref: this._children()[currentPage], 245 ref: this._children()[currentPage],
231 from: prevPage, 246 from: prevPage,
232 }); 247 });
  248 +
233 }, 249 },
234 250
235 _updateScrollValue(value) { 251 _updateScrollValue(value) {
@@ -252,10 +268,6 @@ const ScrollableTabView = React.createClass({ @@ -252,10 +268,6 @@ const ScrollableTabView = React.createClass({
252 return React.Children.map(children, (child) => child); 268 return React.Children.map(children, (child) => child);
253 }, 269 },
254 270
255 - setNativeProps(nativeProps) {  
256 - this._root.setNativeProps(nativeProps);  
257 - },  
258 -  
259 render() { 271 render() {
260 let overlayTabs = (this.props.tabBarPosition === 'overlayTop' || this.props.tabBarPosition === 'overlayBottom'); 272 let overlayTabs = (this.props.tabBarPosition === 'overlayTop' || this.props.tabBarPosition === 'overlayBottom');
261 let tabBarProps = { 273 let tabBarProps = {
@@ -290,7 +302,9 @@ const ScrollableTabView = React.createClass({ @@ -290,7 +302,9 @@ const ScrollableTabView = React.createClass({
290 }; 302 };
291 } 303 }
292 304
293 - return <View ref={(c) => { this._root = c; }} style={[styles.container, this.props.style, ]} onLayout={this._handleLayout}> 305 + let heightStyle = this.state.currentPageContentHeight ? {height: this.state.currentPageContentHeight} : null;
  306 +
  307 + return <View style={[styles.container, heightStyle, this.props.style, ]} onLayout={this._handleLayout}>
294 {this.props.tabBarPosition === 'top' && this.renderTabBar(tabBarProps)} 308 {this.props.tabBarPosition === 'top' && this.renderTabBar(tabBarProps)}
295 {this.renderScrollableContent()} 309 {this.renderScrollableContent()}
296 {(this.props.tabBarPosition === 'bottom' || overlayTabs) && this.renderTabBar(tabBarProps)} 310 {(this.props.tabBarPosition === 'bottom' || overlayTabs) && this.renderTabBar(tabBarProps)}
@@ -143,11 +143,13 @@ let styles = StyleSheet.create({ @@ -143,11 +143,13 @@ let styles = StyleSheet.create({
143 title: { 143 title: {
144 fontSize: 18, 144 fontSize: 18,
145 lineHeight: 28, 145 lineHeight: 28,
  146 + paddingTop: -(28 - 18) / 2 - 2,
146 }, 147 },
147 desc: { 148 desc: {
148 fontSize: 14, 149 fontSize: 14,
149 lineHeight: 23, 150 lineHeight: 23,
150 color: '#888888', 151 color: '#888888',
  152 + paddingTop: -(23 - 14) / 2,
151 }, 153 },
152 thumbs: { 154 thumbs: {
153 marginTop: 15, 155 marginTop: 15,
@@ -29,6 +29,7 @@ const { @@ -29,6 +29,7 @@ const {
29 29
30 let {width, height} = Dimensions.get('window'); 30 let {width, height} = Dimensions.get('window');
31 let bannerHeight = Math.ceil((363 / 750) * width); 31 let bannerHeight = Math.ceil((363 / 750) * width);
  32 +let sectionBarHeight = 41;
32 33
33 export default class Section extends React.Component { 34 export default class Section extends React.Component {
34 35
@@ -137,13 +138,14 @@ export default class Section extends React.Component { @@ -137,13 +138,14 @@ export default class Section extends React.Component {
137 this._renderRow = this._renderRow.bind(this); 138 this._renderRow = this._renderRow.bind(this);
138 this._renderSeparator = this._renderSeparator.bind(this); 139 this._renderSeparator = this._renderSeparator.bind(this);
139 this._updateScrollValue = this._updateScrollValue.bind(this); 140 this._updateScrollValue = this._updateScrollValue.bind(this);
140 - this._updateScrollableTableViewHeight = this._updateScrollableTableViewHeight.bind(this); 141 + this._getCurrentPageHeight = this._getCurrentPageHeight.bind(this);
141 142
142 this.dataSource = new ListView.DataSource({ 143 this.dataSource = new ListView.DataSource({
143 rowHasChanged: (r1, r2) => !Immutable.is(r1, r2), 144 rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
144 sectionHeaderHasChanged: (s1, s2) => !Immutable.is(s1, s2), 145 sectionHeaderHasChanged: (s1, s2) => !Immutable.is(s1, s2),
145 }); 146 });
146 147
  148 + this.initialPageHeight = height - bannerHeight - sectionBarHeight;
147 this.currentPage = 0; 149 this.currentPage = 0;
148 this.tabs = ['最新', '热门']; 150 this.tabs = ['最新', '热门'];
149 151
@@ -196,13 +198,11 @@ export default class Section extends React.Component { @@ -196,13 +198,11 @@ export default class Section extends React.Component {
196 ref={(c) => { 198 ref={(c) => {
197 this.scrollableTabView = c; 199 this.scrollableTabView = c;
198 }} 200 }}
199 - style={{height: this.state.scrollableTabViewHeight}}  
200 renderTabBar={false} 201 renderTabBar={false}
201 initialPage={this.currentPage} 202 initialPage={this.currentPage}
202 onScroll={this._updateScrollValue} 203 onScroll={this._updateScrollValue}
203 - onChangeTab={(tab) => {  
204 - this._updateScrollableTableViewHeight(tab.i, true);  
205 - }} 204 + getCurrentPageHeight={this._getCurrentPageHeight}
  205 + prerenderingSiblingsNumber={Infinity}
206 > 206 >
207 <SectionList 207 <SectionList
208 ref={(c) => { 208 ref={(c) => {
@@ -214,9 +214,7 @@ export default class Section extends React.Component { @@ -214,9 +214,7 @@ export default class Section extends React.Component {
214 onPressSectionTag={this.props.onPressSectionTag} 214 onPressSectionTag={this.props.onPressSectionTag}
215 onPressComment={this.props.onPressComment} 215 onPressComment={this.props.onPressComment}
216 onPressLike={this.props.onPressLike} 216 onPressLike={this.props.onPressLike}
217 - onContentSizeChange={(width, height) => {  
218 - this._updateScrollableTableViewHeight(0);  
219 - }} 217 + onContentSizeChange={(width, height) => {}}
220 /> 218 />
221 <SectionList 219 <SectionList
222 ref={(c) => { 220 ref={(c) => {
@@ -228,9 +226,7 @@ export default class Section extends React.Component { @@ -228,9 +226,7 @@ export default class Section extends React.Component {
228 onPressSectionTag={this.props.onPressSectionTag} 226 onPressSectionTag={this.props.onPressSectionTag}
229 onPressComment={this.props.onPressComment} 227 onPressComment={this.props.onPressComment}
230 onPressLike={this.props.onPressLike} 228 onPressLike={this.props.onPressLike}
231 - onContentSizeChange={(width, height) => {  
232 - this._updateScrollableTableViewHeight(1);  
233 - }} 229 + onContentSizeChange={(width, height) => {}}
234 /> 230 />
235 </ScrollableTabView> 231 </ScrollableTabView>
236 ); 232 );
@@ -246,7 +242,7 @@ export default class Section extends React.Component { @@ -246,7 +242,7 @@ export default class Section extends React.Component {
246 <SectionTabBar 242 <SectionTabBar
247 style={{borderBottomWidth: 0.5, borderBottomColor: '#e0e0e0',}} 243 style={{borderBottomWidth: 0.5, borderBottomColor: '#e0e0e0',}}
248 tabs={this.tabs} 244 tabs={this.tabs}
249 - activeTab={this.state.currentPage} 245 + activeTab={this.currentPage}
250 scrollValue={this.state.scrollValue} 246 scrollValue={this.state.scrollValue}
251 goToPage={(page) => this._goToPage(page)} 247 goToPage={(page) => this._goToPage(page)}
252 /> 248 />
@@ -263,6 +259,10 @@ export default class Section extends React.Component { @@ -263,6 +259,10 @@ export default class Section extends React.Component {
263 } 259 }
264 260
265 _goToPage(page) { 261 _goToPage(page) {
  262 + this.currentPage = page;
  263 + // this.setState({
  264 + // currentPage: this.currentPage,
  265 + // });
266 this.scrollableTabView && this.scrollableTabView.goToPage(page); 266 this.scrollableTabView && this.scrollableTabView.goToPage(page);
267 } 267 }
268 268
@@ -270,37 +270,20 @@ export default class Section extends React.Component { @@ -270,37 +270,20 @@ export default class Section extends React.Component {
270 this.state.scrollValue.setValue(value); 270 this.state.scrollValue.setValue(value);
271 } 271 }
272 272
273 - _updateScrollableTableViewHeight(tabIndex, onChangeTab = false) {  
274 - if (tabIndex > this.tabs.length - 1) {  
275 - return; 273 + _getCurrentPageHeight(page) {
  274 + let ref = null;
  275 + if (page == 0) {
  276 + ref = this.tab1;
  277 + } else {
  278 + ref = this.tab2;
276 } 279 }
277 280
278 - this.timer = setTimeout(() => {  
279 - if (onChangeTab) {  
280 - this.currentPage = tabIndex;  
281 - this.setState({  
282 - currentPage: this.currentPage,  
283 - });  
284 - }  
285 -  
286 - let ref = null;  
287 - if (tabIndex == 0) {  
288 - ref = this.tab1;  
289 - } else {  
290 - ref = this.tab2;  
291 - }  
292 -  
293 - if (!ref) {  
294 - return;  
295 - } 281 + if (!ref) {
  282 + return this.initialPageHeight;
  283 + }
296 284
297 - let height = ref.state.contentHeight;  
298 - this.scrollableTabView && this.scrollableTabView.setNativeProps({  
299 - style: {  
300 - height,  
301 - },  
302 - });  
303 - }, 300); 285 + let height = ref.state.contentHeight;
  286 + return height;
304 } 287 }
305 288
306 render() { 289 render() {
@@ -329,7 +312,7 @@ export default class Section extends React.Component { @@ -329,7 +312,7 @@ export default class Section extends React.Component {
329 this.props.onRefresh && this.props.onRefresh(); 312 this.props.onRefresh && this.props.onRefresh();
330 }} 313 }}
331 onEndReached={() => { 314 onEndReached={() => {
332 - this.props.onEndReached && this.props.onEndReached(this.currentPage); 315 + this.props.onEndReached && this.props.onEndReached(this.scrollableTabView.state.currentPage);
333 }} 316 }}
334 renderFooter={() => { 317 renderFooter={() => {
335 if (endReached) { 318 if (endReached) {
@@ -45,9 +45,9 @@ export default class SectionTabBar extends React.Component { @@ -45,9 +45,9 @@ export default class SectionTabBar extends React.Component {
45 } 45 }
46 46
47 componentWillReceiveProps(nextProps) { 47 componentWillReceiveProps(nextProps) {
48 - this.setState({  
49 - activeTab: nextProps.activeTab  
50 - }); 48 + // this.setState({
  49 + // activeTab: nextProps.activeTab
  50 + // });
51 } 51 }
52 52
53 renderTabOption(name, page) { 53 renderTabOption(name, page) {
@@ -30,6 +30,7 @@ const { @@ -30,6 +30,7 @@ const {
30 let {width, height} = Dimensions.get('window'); 30 let {width, height} = Dimensions.get('window');
31 let navbarHeight = (Platform.OS === 'android') ? 50 : 64; 31 let navbarHeight = (Platform.OS === 'android') ? 50 : 64;
32 let userBgHieght = Math.ceil((490 / 750) * width); 32 let userBgHieght = Math.ceil((490 / 750) * width);
  33 +let sectionBarHeight = 41;
33 34
34 export default class User extends React.Component { 35 export default class User extends React.Component {
35 36
@@ -154,6 +155,7 @@ export default class User extends React.Component { @@ -154,6 +155,7 @@ export default class User extends React.Component {
154 constructor(props) { 155 constructor(props) {
155 super (props); 156 super (props);
156 157
  158 + this.initialPageHeight = height - userBgHieght - sectionBarHeight;
157 this.currentPage = 0; 159 this.currentPage = 0;
158 this.tabs = ['我的帖子', '我赞过的', '我的回复']; 160 this.tabs = ['我的帖子', '我赞过的', '我的回复'];
159 this.scrollableTabView = null; 161 this.scrollableTabView = null;
@@ -168,6 +170,7 @@ export default class User extends React.Component { @@ -168,6 +170,7 @@ export default class User extends React.Component {
168 this._renderSeparator = this._renderSeparator.bind(this); 170 this._renderSeparator = this._renderSeparator.bind(this);
169 this._updateHorizontalScrollValue = this._updateHorizontalScrollValue.bind(this); 171 this._updateHorizontalScrollValue = this._updateHorizontalScrollValue.bind(this);
170 this._updateVerticalScrollValue = this._updateVerticalScrollValue.bind(this); 172 this._updateVerticalScrollValue = this._updateVerticalScrollValue.bind(this);
  173 + this._getCurrentPageHeight = this._getCurrentPageHeight.bind(this);
171 174
172 this.dataSource = new ListView.DataSource({ 175 this.dataSource = new ListView.DataSource({
173 rowHasChanged: (r1, r2) => !Immutable.is(r1, r2), 176 rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
@@ -204,13 +207,11 @@ export default class User extends React.Component { @@ -204,13 +207,11 @@ export default class User extends React.Component {
204 ref={(c) => { 207 ref={(c) => {
205 this.scrollableTabView = c; 208 this.scrollableTabView = c;
206 }} 209 }}
207 -  
208 renderTabBar={false} 210 renderTabBar={false}
209 initialPage={this.currentPage} 211 initialPage={this.currentPage}
210 onScroll={this._updateHorizontalScrollValue} 212 onScroll={this._updateHorizontalScrollValue}
211 - onChangeTab={(tab) => {  
212 - this._updateScrollableTableViewHeight(tab.i, true);  
213 - }} 213 + getCurrentPageHeight={this._getCurrentPageHeight}
  214 + prerenderingSiblingsNumber={Infinity}
214 > 215 >
215 216
216 <CommunityList 217 <CommunityList
@@ -223,9 +224,7 @@ export default class User extends React.Component { @@ -223,9 +224,7 @@ export default class User extends React.Component {
223 onPressSectionTag={this.props.onPressSectionTag} 224 onPressSectionTag={this.props.onPressSectionTag}
224 onPressComment={this.props.onPressComment} 225 onPressComment={this.props.onPressComment}
225 onPressLike={this.props.onPressLike} 226 onPressLike={this.props.onPressLike}
226 - onContentSizeChange={(width, height) => {  
227 - this._updateScrollableTableViewHeight(0);  
228 - }} 227 + onContentSizeChange={(width, height) => {}}
229 /> 228 />
230 229
231 <CommunityList 230 <CommunityList
@@ -238,9 +237,7 @@ export default class User extends React.Component { @@ -238,9 +237,7 @@ export default class User extends React.Component {
238 onPressSectionTag={this.props.onPressSectionTag} 237 onPressSectionTag={this.props.onPressSectionTag}
239 onPressComment={this.props.onPressComment} 238 onPressComment={this.props.onPressComment}
240 onPressLike={this.props.onPressLike} 239 onPressLike={this.props.onPressLike}
241 - onContentSizeChange={(width, height) => {  
242 - this._updateScrollableTableViewHeight(1);  
243 - }} 240 + onContentSizeChange={(width, height) => {}}
244 /> 241 />
245 242
246 <ReplyList 243 <ReplyList
@@ -250,9 +247,7 @@ export default class User extends React.Component { @@ -250,9 +247,7 @@ export default class User extends React.Component {
250 data={rowData.get('reply')} 247 data={rowData.get('reply')}
251 onPressAvatar={this.props.onPressAvatar} 248 onPressAvatar={this.props.onPressAvatar}
252 onPressReply={this.props.onPressReply} 249 onPressReply={this.props.onPressReply}
253 - onContentSizeChange={(width, height) => {  
254 - this._updateScrollableTableViewHeight(2);  
255 - }} 250 + onContentSizeChange={(width, height) => {}}
256 /> 251 />
257 252
258 </ScrollableTabView> 253 </ScrollableTabView>
@@ -296,6 +291,7 @@ export default class User extends React.Component { @@ -296,6 +291,7 @@ export default class User extends React.Component {
296 } 291 }
297 292
298 _goToPage(page) { 293 _goToPage(page) {
  294 + this.currentPage = page;
299 this.scrollableTabView && this.scrollableTabView.goToPage(page); 295 this.scrollableTabView && this.scrollableTabView.goToPage(page);
300 } 296 }
301 297
@@ -307,39 +303,22 @@ export default class User extends React.Component { @@ -307,39 +303,22 @@ export default class User extends React.Component {
307 this.state.scrollValueV.setValue(value); 303 this.state.scrollValueV.setValue(value);
308 } 304 }
309 305
310 - _updateScrollableTableViewHeight(tabIndex, onChangeTab = false) {  
311 - if (tabIndex > this.tabs.length - 1) {  
312 - return; 306 + _getCurrentPageHeight(page) {
  307 + let ref = null;
  308 + if (page == 0) {
  309 + ref = this.tab1;
  310 + } else if (page == 1) {
  311 + ref = this.tab2;
  312 + } else {
  313 + ref = this.tab3;
  314 + }
  315 +
  316 + if (!ref) {
  317 + return this.initialPageHeight;
313 } 318 }
314 319
315 - this.timer = setTimeout(() => {  
316 - if (onChangeTab) {  
317 - this.currentPage = tabIndex;  
318 - this.setState({  
319 - currentPage: this.currentPage,  
320 - });  
321 - }  
322 -  
323 - let ref = null;  
324 - if (tabIndex == 0) {  
325 - ref = this.tab1;  
326 - } else if (tabIndex == 1) {  
327 - ref = this.tab2;  
328 - } else {  
329 - ref = this.tab3;  
330 - }  
331 -  
332 - if (!ref) {  
333 - return;  
334 - }  
335 -  
336 - let height = ref.state.contentHeight;  
337 - this.scrollableTabView && this.scrollableTabView.setNativeProps({  
338 - style: {  
339 - height,  
340 - },  
341 - });  
342 - }, 300); 320 + let height = ref.state.contentHeight;
  321 + return height;
343 } 322 }
344 323
345 render() { 324 render() {