可以从嵌套在选项卡中的堆栈中的屏幕中隐藏选项卡导航器吗?

Possible to hide tab navigator from screen in stack nested in tab?

我有一个带有一些屏幕的 Stack Navigator 和一个像“Profile”这样的初始路径,当我从“Profile”屏幕通过 navigation.navigate("Options") 导航到“Options”时,我不想查看底部的标签。这是我所拥有的示例:

ProfileNav.js

export default function ProfileNav () {
   return (
      <Stack.Navigator initialRoutName="Profile">
         <Stack.Screen name="Profile" component={ProfileScreen}>
         <Stack.Screen name="Options" component={OptionsScreen}>
      </Stack.Navigator>
   );
};

TabNav.js

export default function TabNav () {
   return (
      <Tab.Navigator initialRouteName="Home">
         <Tab.Screen name="Home" component={HomeScreen}>
         <Tab.Screen name="ProfileNav" component={ProfileNav}>
      </Tab.Navigator>
   );
};

我正在使用 React Navigation v6。我已经看到 Hiding tab bar in specific screens 文档描述了如何切换屏幕以实现从单个屏幕隐藏选项卡,但在这种情况下,我试图让 ProfileNav 堆栈的父屏幕仍然显示底部的选项卡,但我不希望堆栈中的其余屏幕显示它们,这不是文档帮助实现的,除非我错过了什么。

那么如何实现隐藏底部选项卡从嵌套在选项卡导航器中的堆栈导航器的 select 屏幕?

我也试过将 tabBarVisible 传递到“选项”屏幕选项中,但这没有用。

您需要改为从 StackNavigator 调用 TabNavigator 堆栈,这应该有效。

export default function TabNav () {
   return (
      <Tab.Navigator>
         <Tab.Screen name="Home" component={HomeScreen}>
         <Tab.Screen name="Profile" component={ProfileScreen}>
      </Tab.Navigator>
   );
};

return(<NavigationContainer
>
    <Stack.Navigator initialRoutName="Home">
      <Stack.Screen name="Home" component={TabNav} />
      <Stack.Screen name="Options" component={OptionsScreen} />
    </Stack.Navigator>

 </NavigationContainer>)

你可以使用来自 @react-navigation/native

的 react 的 useLayoutEffect 和 getFocusedRouteNameFromRoute 函数

首先,我们需要从选项卡导航器参数中提取导航和路由

然后在每次更改焦点布局时使用 useLayoutEffect 我们正在检查焦点路由名称 如果重点路线名称与我们的路线名称匹配(在您的情况下为“Options”),将在哪里设置“tabBarVisible”为“false”

export default function ProfileNav ({ navigation, route }) {
    React.useLayoutEffect(() => {
        const routeName = getFocusedRouteNameFromRoute(route);
        if (routeName == "Options") {
        navigation.setOptions({ tabBarVisible: false });
        } else {
        navigation.setOptions({ tabBarVisible: true });
        }
    }, [navigation, route]);
   return (
      <Stack.Navigator initialRoutName="Profile">
         <Stack.Screen name="Profile" component={ProfileScreen}>
         <Stack.Screen name="Options" component={OptionsScreen}>
      </Stack.Navigator>
   );
};

您可以将navigationContainerRef传递给NavigationContainer并通过TabNav组件中的getCurrentRoute获取当前路由名称,以隐藏特定的标签栏由不同导航器处理的屏幕。

然后,将路由名称作为状态传递给选项卡导航器,并决定哪些屏幕显示选项卡栏,哪些不显示。

在这种情况下,您只想显示路线 ProfileTabBar。这是一个最小的工作示例。

import React, {useState} from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {NavigationContainer} from '@react-navigation/native';
import { createNavigationContainerRef } from "@react-navigation/native"

const Stack = createNativeStackNavigator()

function ProfileNav () {
   return (
      <Stack.Navigator initialRoutName="Profile">
         <Stack.Screen name="Profile" component={ProfileScreen} />
         <Stack.Screen name="Options" component={OptionsScreen} />
      </Stack.Navigator>
   );
}

const Tab = createBottomTabNavigator();

function TabNav (props) {
  const hide = props.routeName != "Profile"
   return (
      <Tab.Navigator initialRouteName="Home">
         <Tab.Screen name="Home" component={HomeScreen} />
         <Tab.Screen name="ProfileNav" component={ProfileNav} options={{
          headerShown: false,
          tabBarStyle: { display: hide ? "none" : "flex" }
        }} />
      </Tab.Navigator>
   );
}

function HomeScreen() {
  return <View></View>
}

function ProfileScreen(props) {
  return <View>
     <Button title="Nav to options" onPress={() => props.navigation.navigate("Options")}></Button>
  </View>
}

function OptionsScreen() {
  return <View></View>
}

const ref = createNavigationContainerRef();

export default function App() {
  const [routeName, setRouteName] = useState();

  return (
    <NavigationContainer
      ref={ref}
      onReady={() => {
        setRouteName(ref.getCurrentRoute().name)
      }}
      onStateChange={async () => {
        const previousRouteName = routeName;
        const currentRouteName = ref.getCurrentRoute().name;
        setRouteName(currentRouteName);
      }}
    >
       <TabNav routeName={routeName} />
     </NavigationContainer>
  );
}

这是一个有效的 snack