如何在React Navigation 6中隐藏特定屏幕中的tabBar?

问题描述 投票:0回答:7

如何在

react-navigation 6
中隐藏特定屏幕中的选项卡栏...无需更改导航结构,因为它是此处文档中唯一可用的选项

react-native react-navigation react-navigation-v6
7个回答
5
投票

有时我使用这种方法

import { getFocusedRouteNameFromRoute } from ‘@react-navigation/native’;


 export const MainNavigator = () => {
  const getTabBarVisibility = (route) => {
    const routeName = getFocusedRouteNameFromRoute(route);
    const hideOnScreens = [SCREENS.REVIEW_ORDER, SCREENS.ORDER_PAYMENT]; // put here name of screen where you want to hide tabBar
    return hideOnScreens.indexOf(routeName) <= -1;
  };
  return (
    <Tab.Navigator>
      <Tab.Screen
        name={SCREENS.ORDER}
        component={OrderNavigator}
        options={({ route }) => ({
          tabBarVisible: getTabBarVisibility(route),
        })}
      />
      <Tab.Screen name={SCREENS.REWARDS} component={SweetRewardsNavigator} />
      <Tab.Screen name={SCREENS.MY_ACCOUNT} component={MyAccountNavigator} />
    </Tab.Navigator>
  );
};

1
投票

我就是这么做的。

我正在寻找一种方法来隐藏 ProductsRoutes 上所有屏幕中的 tabBar(主屏幕除外)。(ProductsRoutes 导航器上的初始路线)

这是产品导航器:

const ProductsRoutes = (): JSX.Element => {
  return (
    <Navigator
      initialRouteName="Home"
      screenOptions={{
        headerShown: false,
      }}
    >
      <Screen name="Home" component={Home} />
      <Screen name="Details" component={Details} />
      <Screen name="Cart" component={Cart} />
      <Screen name="Catalog" component={Catalog} />
      <Screen name="Sales" component={Sales} />
      <Screen name="Favorites" component={Favorites} />
    </Navigator>
  );
};

在我正在使用的 TabRoutes 上

import { getFocusedRouteNameFromRoute } from '@react-navigation/native';

了解 ProductsNavigator 上的哪个屏幕是主屏幕,哪个不是主屏幕。 根据该条件,我可以将 display:'none' 或 'display:'flex' 设置为 Screen props 上的 tabBarStyle prop:

import { getFocusedRouteNameFromRoute } from '@react-navigation/native';

const TabRoutes = (): JSX.Element => {
  return (
    <Navigator
      screenOptions={{
        headerShown: false,
      }}
    >
      <Screen
        name="Store"
        component={ProductsRoutes}
        options={({ route }) => {
          const focusedRouteName = getFocusedRouteNameFromRoute(route);
          if (focusedRouteName === 'Home') {
            return {
              tabBarStyle: { display: 'flex' },
            };
          }

          return {
            tabBarStyle: { display: 'none' },
          };
        }}
      />
    </Navigator>
  );
};

希望这对您有所帮助


1
投票

关键字是调用

setOptions
并将
tabBarStyle
设置为
{display:'none'}

首先,我们在父导航器上设置 id

 <Tab.Navigator
      id="tabs"
      tabBar={props => <FooterTabs {...props} style={{display: 'flex'}} />} //<-- add a style with display:flex means tabbar is visible by default
      >
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Search" component={SearchScreen} />
      <Tab.Screen name="Chat" component={ChatScreen} />
    </Tab.Navigator>

假设我们想隐藏聊天屏幕中的标签栏

在聊天屏幕中,键入这样的代码

const ChatScreen = ({navigation}) => {
  useEffect(() => {
    navigation.getParent('tabs').setOptions({tabBarStyle: {display: 'none'}});
    return ()=>{
    //when leave this screen, and the hooks disposed, we set tabBarStyle to {}, means we will use the default style defined above, that is display:'flex'
 
      navigation.getParent('tabs').setOptions({tabBarStyle: {}});
    };
  }, [navigation]);
...

你可能会注意到根选项卡导航器中的选项卡栏是一个自定义组件,所以在

FooterTabs
内部,关键代码是这样的

const FooterTabs = props => {
  const {state, navigation, descriptors, insets, style} = props;
  const focusedRoute = state.routes[state.index];
  const focusedDescriptor = descriptors[focusedRoute.key];
  const focusedOptions = focusedDescriptor.options;

  const {
    tabBarShowLabel,
    tabBarHideOnKeyboard = false,
    tabBarVisibilityAnimationConfig,
    tabBarStyle, //<-- this is get from options,which we set from sub screens 
    tabBarBackground,
    tabBarActiveTintColor,
    tabBarInactiveTintColor,
    tabBarActiveBackgroundColor,
    tabBarInactiveBackgroundColor,
  } = focusedOptions;

  return (
    <HStack
      style={{...props.style, ...tabBarStyle}} //<-- we set the style over here, so when in some specific screen set tabbarstyle to override the display property to 'none', can final make tabbar hidden
      ...

上面的代码是从官方底部标签栏组件

获取的

0
投票
var scroll = 0; // at top

const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
    let contentOffsetY = e.nativeEvent.contentOffset.y;
    let diff = contentOffsetY - scroll;
    if (diff < 0) {
      navigation.setOptions({tabBarStyle: {display: 'flex'}});
    } else {
      navigation.setOptions({tabBarStyle: {display: 'none'}});
    }
    scroll = contentOffsetY;
  };

将其传递给任何滚动视图组件的 onScroll


0
投票

在我的例子中,我有一个堆栈导航器屏幕,可以在其中隐藏父母和祖父母导航器的选项卡栏和标题。

export const MyNav = ({
  route,
  navigation
}) => {

   React.useLayoutEffect(() => {
    
        const routeName = getFocusedRouteNameFromRoute(route);


        if (routeName === 'RouteThatNeedsHiddenTabBarsAndHiddenHeader') {
          navigation.setOptions({ tabBarStyle: { display: 'none' } });
          navigation.getParent()?.setOptions({ headerShown: false });
          navigation.getParent()?.getParent()?.setOptions({ tabBarStyle: { display: 'none' } });
        } else {
          navigation.setOptions({
            tabBarStyle: { ...defaultTabBarStyle, display: 'flex' }
          });
          navigation.getParent()?.setOptions({ headerShown: true });
          navigation.getParent()?.getParent()?.setOptions({ tabBarStyle: {display: 'flex' });
        }
      }, [navigation, route]);

      return (
        <Stack.Navigator>
          <Stack.Screen
            name="NormalRoute"
            component={NormalScreen}
          />
          
          <Stack.Screen
            name="RouteThatNeedsHiddenTabBarAndHiddenHeader"
            component={SpecialScreen}              />
        </Stack.Navigator>
      );
  }

如果只需要调整 1 个屏幕,一种更简单的方法是在目标屏幕中运行代码,如下所述:

https://stackoverflow.com/a/70153935/1979861


0
投票

对我来说

getFocusedRouteNameFromRoute
返回了
undefined
。所以我必须实施其他解决方案。 我在 redux 中创建了名为 state 的导航,其中添加了属性
tabBarHidden
。然后在选项卡导航屏幕中我这样做了。

const Tab = createBottomTabNavigator();

const MainNavigator = () => {
  const tabBarHidden = useSelector(state => state.navigation.tabBarHidden); <-- redux selector

  return <Tab.Navigator tabBar={props => (
     <View style={{
         display: tabBarHidden ? 'none' : 'flex'
      }}>
       <BottomTabBar {...props} />       <-- imported from @react-navigation/bottom-tabs
     </View>
  )}>
    // your tabs
  </Tab.Navigator>
}

然后你可以使用 redux actions 来更新属性 例如,如果您想在聊天组件中隐藏选项卡栏,您必须执行类似的操作

 useFocusEffect( <-- imported from @react-navigation/native
    useCallback(() => {
     dispatch(hideTabBar()) <-- redux action to set tabBarHidden to true

     return () => {
       dispatch(unhideTabBar())
     }
   }, [dispatch]),
 )

0
投票

我为此创建了一个简单的挂钩,效果完美,只需在任何屏幕上调用它

useHideBottomBar();
即可隐藏该屏幕上的底部栏。更改样式以匹配您的设计。

import React from 'react';
import {useNavigation} from '@react-navigation/native';
import ThemeContext from '../../contexts/ThemeContext';
import useColours from '../useColours';
import {useTheme} from 'react-native-paper';
import {Platform} from 'react-native';
import {themeFontFamily} from '../../helpers/theme';

export function useHideBottomBar() {
  const navigation = useNavigation();
  const {darkMode} = React.useContext(ThemeContext);
  const colours = useColours();
  const theme = useTheme();

  React.useEffect(() => {
    navigation.getParent()?.setOptions({
      tabBarStyle: {display: 'none'},
      tabBarBadgeStyle: {display: 'none'},
    });
    return () =>
      navigation.getParent()?.setOptions({
        tabBarStyle: {
          backgroundColor: darkMode
            ? theme.colors.surface
            : colours.secondary050,
          borderTopColor: darkMode
            ? theme.colors.surfaceVariant
            : colours.secondary200,
          borderTopWidth: 1,
          height: Platform.OS == 'ios' ? 110 : 80,
          display: 'flex',
        },
        tabBarBadgeStyle: {
          ...themeFontFamily.OpenSansSemiBold,
          backgroundColor: colours.errorDark,
          color: colours.white,
          fontSize: 11,
          padding: 0,
          marginTop: 6,
          display: 'flex',
        },
      });
  }, [navigation]);
}
© www.soinside.com 2019 - 2024. All rights reserved.