1、Header的参数设置后无效
每一个navigator只会查看其直接子级进行配置,比如一个页面在一个stackNavigator里,而这个stackNavigator在一个tabNavigator里,那么直接在页面配置 navigationOptions 是无效的,要在stackNavigator里进行配置,例如:
let HomeStack = createStackNavigator({ A });let SettingsStack = createStackNavigator({ B }); HomeStack.navigationOptions = { tabBarLabel: 'Home!', }; SettingsStack.navigationOptions = { tabBarLabel: 'Settings!', };export default createBottomTabNavigator({ HomeStack, SettingsStack, });
2、react-navigation的Header太过繁琐,自由度不高,与组件的信息交互里十分不友好
Header这个问题在项目刚开始对我造成了很大的困扰,可能你有时都不知道在哪个navigation里配置header,有些页面不需要header这又是难以解决的坑,在stackoverflow和issue里也没找到合适的解决方案。
在花费了长时间烦躁的探索后,我静下心来仔细想了一下,react-navigation的header是否有存在的必要?顿时我豁然开朗,header说到底其实也就是个标题栏,最多给你一个回退的Left按钮,但调用this.prop.navigation.goback(),同样也可以实现这一功能,所以为什么不自己封装一个header呢?
如果header作为一个独立的组件,那么就可以在每一个页面里通过import作为组件的一部分,而不需要在navigation里进行参数式配置,这样就不需要受react-navigation的种种限制,与组件的交互也更加方便。
对于Header的组件,我推荐react-native-navbar,结合项目需求进行组件封装
3、对于常见的‘底部标签式导航’布局,应该如何进行构建
[1] 首先,对于最外部的Navigator,需要考虑到加载页面,登录页面等,这些页面都是不需要回退的,只显示一次了,所以使用的是switchNavigator,具体代码如下:
const RootStack = createSwitchNavigator( { Splash: SplashScreen, App: AppStack, Login: LoginScreen }, { initialRouteName: 'Splash' } )export default class App extends React.Component<Props> { render() { return ( <RootStack ref={navigatorRef => { NavigationService.setTopLevelNavigator(navigatorRef) }} /> ) } }
[2]其次是bottomTabNavigator,用于在每个Tab上呈现不同的页面,是APP的入口页面,代码如下:
const tabScreens = { first: { screen: FirstScreen, navigationOptions: { tabBarLabel: '首页', tabBarIcon: ({ tintColor }) => renderIcon('home', tintColor) } }, message: { screen: MessageScreen, navigationOptions: { tabBarLabel: '消息', tabBarIcon: ({ tintColor }) => renderIcon('comments-o', tintColor) } }, mine: { screen: MineScreen, navigationOptions: { tabBarLabel: '我的', tabBarIcon: ({ tintColor }) => renderIcon('user', tintColor) } } }const tabConfig = { tabBarPosition: 'bottom', tabBarOptions: { inactiveTintColor: '#a0a0a0', activeTintColor: basicColor.mainColor, indicatorStyle: { backgroundColor: 'transparent' }, showIcon: true, style: { margin: 0, backgroundColor: '#ffffff', borderTopWidth: 0.66, borderTopColor: '#dddddd' }, tabStyle: { padding: 0, margin: 0 }, labelStyle: { fontSize: 11, margin: 0, marginBottom: 5 }, iconStyle: { marginTop: -3, marginBottom: 0 } }, swipeEnabled: false}const HomeTab = createBottomTabNavigator(tabScreens, tabConfig)
[3]最后,是其他普通页面,一开始我是按照文档推荐的模式:在每一个Tab都建立一个StackNavigator,但是之后发现这样做太繁琐了,每个Tab多了一层stackNavigator不说,有些页面不属于任何Tab栈,那么其位置就很尴尬了,所以决定采用另一种模式:在switchNavigator的下一层创建一个StackNaviagtor,把TabNavigator也当成里面的一个screen,之后所有的需要回退的页面都作为screen存在这个stack里,screens文件夹下每一个文件夹都当是一个screen,用index.js作为出口。
4、在android上页面跳转如何实现ios左右切换的效果
其实react-navigation本身就实现了这个效果,目前文件在 'react-navigation/src/views/StackView/StackViewStyleInterpolator.js',可能版本更新之后又会改变路径
import StackStyleInterpolator from 'react-navigation/src/views/StackView/StackViewStyleInterpolator.js'const AppStack = createStackNavigator( { Home: HomeScreen, Front: FrontScreen, Setting: SettingScreen }, { headerMode: 'none', transitionConfig: () => ({ //设置横向切换动画 screenInterpolator: StackStyleInterpolator.forHorizontal }) } )
5、状态栏StatusBar的位置应该配置在哪
首先我们应该明白StatusBar对于不同的navigator有不同的表现形式:
1.在 SwitchNavigator中的页面配置:每一个页面的statusBar设置都不会影响到另外的页面
2.在StackNavigator、DrawerNavigator中的页面配置:每一次设置statusBar都会重新设置状态栏
3.在TabNavigator中的页面配置:只有页面第一次加载才会重新设置状态栏。
4.综上所诉,结合到项目具体的结构,我们只需要在项目的根Navigator添加
<View style={{ flex: 1 }}>//注意,如果没有flex:1,则页面不会加载出来 <StatusBar backgroundColor="transparent" translucent barStyle="dark-content" /> <RootStack ref={navigatorRef => { NavigationService.setTopLevelNavigator(navigatorRef) }} /> </View>
因为我们项目是采用半透明式状态栏,所以不需要考虑状态栏随不同页面改变而改变的情况,如果有需要可以参考基于路由的不同状态栏配置
6、如何跳转到一个不存在于当前navigator的页面(比如用户信息过期需跳转到登录界面)
这个需要自己封装一个NavigationService,代码如下
import { NavigationActions, StackActions } from 'react-navigation'let _navigatorfunction setTopLevelNavigator(navigatorRef) { _navigator = navigatorRef }function navigate(routeName, params) { _navigator.dispatch( NavigationActions.navigate({ routeName, params }) ) }function resetTo(routeName) { const resetAction = StackActions.reset({ index: 0, actions: [NavigationActions.navigate({ routeName: routeName })] }) _navigator.dispatch(resetAction) }function goBack() { _navigator.dispatch(NavigationActions.back()) }export default { navigate, resetTo, setTopLevelNavigator, goBack }
然后在根Navigator里调用setTopLevelNavigator
<RootStack ref={navigatorRef => { NavigationService.setTopLevelNavigator(navigatorRef) }} />
在其他地方调用NavigationService里的相应方法就可以从根导航器里跳转到任一个界面
7、如何在不传递navigation的情况下在自己封装的Header里调用goback()
在NavigationService里创建goback()方法即可
作者:一只路过的小学生
链接:https://www.jianshu.com/p/f1e48336d1f4
共同学习,写下你的评论
评论加载中...
作者其他优质文章