我知道之前曾有人问过这个问题,但仅适用于旧版本的react-navigation。从那以后,一些事情发生了变化。 createBottomTabNavigator
使得创建底部导航器的速度大大提高,并且功能jumpToIndex()
不再存在。
我的问题是如何创建类似Instagram的底部标签,其中第一,第二,第四和第五个导航按钮的作用类似于常规标签导航器,而中间按钮(screen3
)打开模式{{1} }。
我已经使用screen3Modal
和createBottomTabNavigator
在react-navigation 3.x.x中进行了尝试。
createStackNavigator
此代码创建选项卡导航和模式导航。可以从另一个屏幕打开模态,但是在选项卡导航器中无法使用。我收到错误消息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 />;
}
}
答案 0 :(得分:1)
您可以将所有内容包装在同一个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 />;
}
}
答案 1 :(得分:1)
我找到了一个相对简单的解决方案:
使用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>
答案 2 :(得分:0)
我花了几个小时来解决这个问题。
这是经过全面测试的解决方案:
const FinalTabsStack = createStackNavigator(
{
tabs: TabNavigator,
screen1: Screen1Navigator,
}, {
mode: 'modal',
}
)
使用this指南中的标签堆栈创建应用容器
在TabNavigator
中createBottomTabNavigator
内,返回特定选项卡(screen3)的空组件(以关闭react-navigator的导航),并手动处理{{1}内的选项卡},为其创建自定义组件。
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
有点复杂,但是可以用。
答案 3 :(得分:0)
我发现了一种基于this github issue的更好的解决方案。
您只需要添加特定的选项卡配置,在您的情况下screen3中,就可以看到事件NavigationOptions(您已经拥有了),但是,您必须将其作为参数接收,因为没有任何上下文可用于this
,如您所用。要更正您编写的第一个代码,我将其更改为此,并且可以正常工作:
navigationOptions: ({ navigation }) => ({
tabBarOnPress: ({ navigation }) => {
navigation.navigate("screen3Modal");
}
})
答案 4 :(得分:0)
可以做的是防止Tab键按下事件的默认操作,并使用所需的动画导航到所需的屏幕。
就我而言,我想以iOS 13的演示文稿样式在iOS中打开一个模式,我所做的是防止出现以下默认操作
<Tab.Screen name="screen1"
component={ EmptyScreen } // empty screen becuase I want nothing to present here so it was a component that returns null which is given bellow
listeners={({ navigation, route }) => ({
tabPress: e => {
e.preventDefault();
navigation.navigate('modalscreen');
},
})} />
const EmptyScreen = () => {
return null
}
上面代码中使用的'modelscreen'来自如下所示的导航堆栈。上面代码中Tab.Screen的Tab导航器是 otherstacknavigation 中的屏幕之一,用于以下导航。
const MainStack = ({ initialRoute }) => {
return (
<Stack.Navigator
initialRouteName="otherstacknavigation"
screenOptions={{
headerShown: false,
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.ModalPresentationIOS
}}>
<Stack.Screen name='modalscreen'
component={modalscreen}
options={{
headerShown: false
}} />
<Stack.Screen name='otherstacknavigation'
component={otherstacknavigation}
initialParams={{ initialRoute: initialRoute }}/>
</Stack.Navigator>
);
}
export default MainStack;
您可以像下面一样导入 TransitionPresets ;
import { createStackNavigator, TransitionPresets } from '@react-navigation/stack'
因此,就我而言,我有第一个主堆栈导航器,即上面的MainStack。它还有另一个堆栈导航器,它是MainStack上方的otherstacknavigation。该其他堆栈导航具有一个屏幕,该屏幕的组件为Tab导航器。上面代码中的Tab.Screen来自该Tab导航器。现在,从该标签导航器的一个标签中,我导航到MainStack中的“ modelscreen”。我必须创建此MainStack导航器才能实现此功能,否则我的代码将从otherstacknavigation开始。因为,ModalPresentationIOS只能应用于堆栈级别,而不能应用于屏幕级别。
我正在使用react-navigation-5。*,我认为它已经回答了在这种情况下可能出现的多个问题。