有时我使用这种方法
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>
);
};
我就是这么做的。
我正在寻找一种方法来隐藏 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>
);
};
希望这对您有所帮助
关键字是调用
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
...
上面的代码是从官方底部标签栏组件
获取的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
在我的例子中,我有一个堆栈导航器屏幕,可以在其中隐藏父母和祖父母导航器的选项卡栏和标题。
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 个屏幕,一种更简单的方法是在目标屏幕中运行代码,如下所述:
对我来说
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]),
)
我为此创建了一个简单的挂钩,效果完美,只需在任何屏幕上调用它
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]);
}