我知道之前已经问过这个问题,但仅限于旧版本的react-navigation。从那时起,一些事情发生了变化。 createBottomTabNavigator
使创建底部导航器的速度更快,而且jumpToIndex()
功能不再存在。
我的问题是如何创建类似Instagram的底部选项卡,其中第一,第二,第四和第五个导航按钮像通常的标签导航器一样,中间按钮(screen3
)打开模态screen3Modal
。
我使用createBottomTabNavigator
和createStackNavigator
在react-navigation 3.x.x中尝试过它。
import React, { Component, } from 'react';
import { createBottomTabNavigator, createStackNavigator, createAppContainer, } from 'react-navigation';
import { Screen1, Screen2, Screen3, Screen4, Screen5 } from './screens';
const TabNavigator = createBottomTabNavigator({
screen1: { screen: Screen1, },
screen2: { screen: Screen2, },
screen3: {
screen: () => null,
navigationOptions: () => ({
tabBarOnPress: () => this.props.navigation.navigate('screen3Modal')
})
},
screen4: { screen: Screen4, },
screen5: { screen: Screen5, },
});
const StackNavigator = createStackNavigator({
Home: { screen: TabNavigator },
screen3Modal: { screen: Screen3, },
},
{
initialRouteName: 'Home',
});
const StackNavigatorContainer = createAppContainer(StackNavigator);
export default class App extends Component {
render() {
return <StackNavigatorContainer />;
}
}
此代码创建选项卡导航和模态导航。模态可以从另一个屏幕打开,但它不能在选项卡导航器中工作。我得到了错误消息undefined is not an object (evaluating '_this.props.navigation')
您可以将所有内容包装在同一个StackNavigator中,这样您就可以轻松导航到其他路径。在这里,我将screen3作为默认路由传递,但您可以将其更改为您想要的任何内容。
import React, { Component, } from 'react';
import { createBottomTabNavigator, createStackNavigator, createAppContainer, } from 'react-navigation';
import { Screen1, Screen2, Screen3, Screen4, Screen5 } from './screens';
const TabNavigator = createBottomTabNavigator({
screen1: { screen: Screen1, },
screen2: { screen: Screen2, },
screen3: { screen: () => null, }, //this.props.navigation.navigate('screen3Modal')
screen4: { screen: Screen4, },
screen5: { screen: Screen5, },
});
const StackNavigator = createStackNavigator({
Home: { screen: TabNavigator },
screen3Modal: { screen: Screen3, },
},
{
initialRouteName: 'screen3Modal',
});
const StackNavigatorContainer = createAppContainer(StackNavigator);
export default class App extends Component {
render() {
return <StackNavigatorContainer />;
}
}
我找到了一个相对简单的解决方案:用display:"none"
隐藏原始导航栏
const TabNavigator = createBottomTabNavigator(
{
screen1: Screen1,
screen2: Screen2,
screen4: Screen4,
screen5: Screen5,
}, {
tabBarOptions: {
style: { display: "none", }
}
},
);
const StackNavigator = createStackNavigator(
{
Home: TabNavigator,
screen3: Screen3
}, {
mode: 'modal',
}
)
export default createAppContainer(StackNavigator);
并在每个屏幕上创建一个新的导航栏
<View style={{ flexDirection: "row", height: 50, justifyContent: "space-evenly", alignItems: "center", width: "100%" }}>
<TouchableOpacity onPress={() => this.props.navigation.navigate("screen1")}><Text>1</Text></TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate("screen2")}><Text>2</Text></TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate("screen3")}><Text>3</Text></TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate("screen4")}><Text>4</Text></TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate("screen5")}><Text>5</Text></TouchableOpacity>
</View>
好吧,我花了几个小时来解决这个问题。
这是完全工作和测试的解决方案:
const FinalTabsStack = createStackNavigator(
{
tabs: TabNavigator,
screen1: Screen1Navigator,
}, {
mode: 'modal',
}
)
TabNavigator
中的createBottomTabNavigator
内部返回特定选项卡的空组件(screen3)(通过react-navigator关闭导航)并通过为defaultNavigationOptions
创建自定义组件来手动处理选项卡。 const TabNavigator = createBottomTabNavigator({
screen1: Screen1Navigator,
screen2: Screen2Navigator,
screen3: () => null,
screen4: Screen4Navigator,
screen5: Screen5Navigator,
}
defaultNavigationOptions: ({ navigation }) => ({
mode: 'modal',
header: null,
tabBarIcon: ({ focused }) => {
const { routeName } = navigation.state;
if (routeName === 'screen3') {
return <Screen3Tab isFocused={focused} />;
}
},
}),
Screen3Tab
内手动单击。 Screen3Tab内部组件: <TouchableWithoutFeedback onPress={this.onPress}>
<Your custom tab component here />
</TouchableWithoutFeedback>
onPress = () => {
this.props.dispatch({ type: 'NAVIGATION_NAVIGATE', payload: {
key: 'screen3',
routeName: 'screen3',
}})
}
redux-saga
NavigationService.navigate(action.payload);
有点复杂,但有效。
我找到了一个基于this github issue的更好的解决方案。你只需添加特定的选项卡配置,在你的情况下screen3事件navigationOptions(你已经拥有它),你非常接近,但是,你必须接收导航作为参数,因为没有任何上下文this
就像你在使用它一样。要更正您编写的第一个代码,我会将其更改为此代码,它将起作用:
navigationOptions: ({ navigation }) => ({
tabBarOnPress: ({ navigation }) => {
navigation.navigate("screen3Modal");
}
})