在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:大概就是这样了,若是你看不懂,请不要吐槽个人表达能力以及排版