在IOS上,react native有官方的TabBar使用,可是android,就須要使用第三方插件或者本身手寫了。react
我在項目中使用了react-native-scrollable-tab-view插件,可是在使用過程當中,遇到了一些問題,沒法知足個人需求,android
因而在這篇文章中記錄一下個人使用心得。ios
使用了react-native-vector-icons插件git
參kao的開源項目:使用reactNative實現的GitHub客戶端,資訊頭條;github
個人項目需求:react-native
和IOS同樣,使用tabBar,底部有兩個tab(主頁,個人),在個人頁面中,不須要頂部標題,而切換到其餘頁面時,須要隱藏底部tabBar。app
在使用react-native-scrollable-tab-view插件時,若是將整個tab插件放在Navigator中,那麼在切換底部tab的時候,標題欄的標題沒法進行切換,而若是將Navigator放在Tab內部,那麼底部TabBar沒法隱藏。ide
上面就是示意圖,下面就是代碼了
flex
關鍵點就是須要根據須要隱藏標題動畫
_setNavigatorRef = (navigator) => { if (navigator !== this._navigator) { this._navigator = navigator; if (navigator) { // Observe focus change events from the owner. this._listeners = [ navigator.navigationContext.addListener('willfocus', this._onWillFocus), ]; } } } ...... componentWillUnmount() { this._listeners && this._listeners.forEach(listener => listener.remove()); } _onWillFocus = (event) => { if(event.data.route.id == 'main') { this.setState({ hideNavBar: true, }); } else { this.setState({ hideNavBar: false, }); } } ...... navBar() { if(!this.state.hideNavBar) { return ( <Navigator.NavigationBar routeMapper={{ LeftButton: this.LeftButton, RightButton: this.RightButton, Title: this.Title }} style={styles.navBar} navigationStyles={NavigatorNavigationBarStyle} //頁面切換的動畫效果 /> ) } else { return <Text style={{height:0, position:'absolute', top:0}} />; } }
index.android.js
import React, { AppRegistry, Component, StyleSheet, Text, View, TouchableOpacity, Platform, Navigator } from 'react-native'; import Icon from 'react-native-vector-icons/Ionicons'; import NavigatorNavigationBarStyle from './LLNavigatorBarStyle'; import Main from './Main'; import TwoView from './TwoView'; import Three from './Three'; class reactNative23 extends Component { constructor(props) { super(props); this.state = { hideNavBar: true, starDatas: null, }; } renderScene = (route, navigator) => { switch(route.id) { case 'two': return <TwoView navigator={navigator}/> case 'three': return <Three navigator={navigator}/> default: return <Main navigator={navigator}/> } } componentWillUnmount() { this._listeners && this._listeners.forEach(listener => listener.remove()); } _onWillFocus = (event) => { if(event.data.route.id == 'main') { this.setState({ hideNavBar: true, }); } else { this.setState({ hideNavBar: false, }); } } _setNavigatorRef = (navigator) => { if (navigator !== this._navigator) { this._navigator = navigator; if (navigator) { // Observe focus change events from the owner. this._listeners = [ navigator.navigationContext.addListener('willfocus', this._onWillFocus), ]; } } } // Nav使用 navBar() { if(!this.state.hideNavBar) { return ( <Navigator.NavigationBar routeMapper={{ LeftButton: this.LeftButton, RightButton: this.RightButton, Title: this.Title }} style={styles.navBar} navigationStyles={NavigatorNavigationBarStyle} //頁面切換的動畫效果 /> ) } else { return <Text style={{height:0, position:'absolute', top:0}} />; } } LeftButton(route, navigator, index, navState) { return ( <TouchableOpacity onPress={() => navigator.pop()} style={styles.navBarLeftButton}> <Icon name='ios-arrow-left' size={30} color='#fff' style={styles.icon} /> </TouchableOpacity> ); } RightButton(route, navigator, index, navState) { return null; } Title(route, navigator, index, navState) { return ( <View style={styles.navBarText}> <Text style={styles.navBarTitleText} numberOfLines={1}> {route.title} </Text> </View> ); } /** * 路由轉跳的效果,默認是FadeAndroid */ configureScene(route, routeStact) { //若是路由有傳 切換方式,則使用 if (route.configureScene) { return route.configureScene; } else { return Navigator.SceneConfigs.FadeAndroid; } } render() { return ( <Navigator ref={this._setNavigatorRef} debugOverlay={false} configureScene={this.configureScene.bind(this)} style={styles.appContainer} //sceneStyle={this.state.hideNavBar ? {marginTop: 0} : styles.sceneStyle} //全部容器的樣式 initialRoute={{id: 'main'}} renderScene={this.renderScene} navigationBar={this.navBar()} /> ); } } const styles = StyleSheet.create({ navBar: { backgroundColor:'#fe4500', height: (Platform.OS === 'ios') ? 64 : 50 }, navBarText: { flex: 1, justifyContent: 'center', alignItems: 'center', width: 250, }, navBarTitleText: { color: '#fff', fontSize: 16, fontWeight: '500', textAlign: 'center', marginHorizontal: 10, marginVertical: 11, }, navBarLeftButton: { paddingLeft: 10, width: 40, height: 50, }, navBarRightButton: { marginRight:5, }, icon: { marginTop:(Platform.OS === 'ios') ? 6: 8, textAlign:'center' } }); AppRegistry.registerComponent('reactNative23', () => reactNative23);
Main.js
import React, { Component, } from 'react-native'; import ScrollableTabView from 'react-native-scrollable-tab-view'; import Home from './Home'; import My from './My'; import TabBar from './TabBar'; export default class Main extends Component { render() { return ( <ScrollableTabView tabBarPosition='bottom' renderTabBar={() => <TabBar />} locked={true} > <Home navigator={this.props.navigator} tabLabel={{tabName: '主頁', iconName: 'ios-home'}}/> <My navigator={this.props.navigator} tabLabel={{tabName: '個人', iconName: 'ios-person'}}/> </ScrollableTabView> ) } }
Home.js
import React, { Component, View, TouchableOpacity, StyleSheet, Text } from 'react-native'; export default class Home extends Component { toTwo = () => { this.props.navigator.push({ id: 'two', title: '第二頁面' }) } render() { return ( <View style={styles.container}> <View style={styles.header}> <Text style={{color: '#fff', fontSize: 16, fontWeight: '500',}}>主頁</Text> </View> <View style={styles.content}> <TouchableOpacity onPress={this.toTwo} style={styles.button}> <Text>跳轉到第二頁</Text> </TouchableOpacity> </View> </View> ) } } const styles = StyleSheet.create({ container: { flex: 1, }, header: { backgroundColor: '#fe4500', height: 50, justifyContent: 'center', alignItems: 'center' }, content: { flex: 1, justifyContent: 'center', alignItems: 'center', }, button: { justifyContent: 'center', alignItems: 'center', height: 50, width: 200, backgroundColor: '#fe4500', } })
不過,這不是最好的解決辦法,應該在返回Main頁面時,應該Home頁面的標題不是NavigationBar,因此會有0.4秒的白屏出現,固然,若是你的項目頂部標題欄是白色的,那就看不出來了。
ps:大概就是這樣了,若是你看不懂,請不要吐槽個人表達能力以及排版