[英]React navigation 5 hide tab bar from stack navigator
I wanted to know how to hide the bottom tab bar from a specific screen inside my stack navigator that is nested on a material bottom tab bar我想知道如何从嵌套在材料底部标签栏上的堆栈导航器内的特定屏幕隐藏底部标签栏
This is my code for my stack navigator这是我的堆栈导航器代码
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import PondScreen from '../screens/PondScreen/PondScreen';
import PondDetailScreen from '../screens/PondScreen/PondDetailScreen';
const Stack = createStackNavigator();
export function PondStack() {
return (
<Stack.Navigator
initialRouteName="PondScreen"
headerMode="none"
mode="card"
>
<Stack.Screen
name="PondScreen"
component={PondScreen}
/>
<Stack.Screen
name="PondDetailScreen"
component={PondDetailScreen}
options={{
tabBarVisible: false
}}
/>
</Stack.Navigator>
);
}
This is my code for my material bottom tab navigator这是我的材料底部选项卡导航器的代码
import React from 'react';
import { View } from 'react-native';
import { createMaterialBottomTabNavigator } from '@react-navigation/material-bottom-tabs';
import { Entypo, Feather } from '@expo/vector-icons';
import { PondStack } from './StackNavigators';
import StockScreen from '../screens/StockScreen';
import OrderScreen from '../screens/OrderScreen';
import SettingsScreen from '../screens/SettingsScreen';
const Tab = createMaterialBottomTabNavigator();
export default function BottomTab() {
return (
<Tab.Navigator
labeled={false}
initialRouteName="Pond"
activeColor="#EB3349"
inactiveColor="#888888"
backBehavior="none"
shifting={true}
barStyle={{
backgroundColor: '#FFFFFF'
}}
>
<Tab.Screen
name="Pond"
component={PondStack}
options={{
tabBarIcon: ({ color}) => (
<View style={{ flex: 1 }}>
<Entypo name="air" color={color} size={20} />
</View>
)
}}
/>
<Tab.Screen
name="Stock"
component={StockScreen}
options={{
tabBarIcon: ({ color }) => (
<View style={{ flex: 1 }}>
<Feather name="box" color={color} size={20} />
</View>
)
}}
/>
<Tab.Screen
name="Order"
component={OrderScreen}
options={{
tabBarIcon: ({ color}) => (
<View style={{ flex: 1 }}>
<Feather name="dollar-sign" color={color} size={20} />
</View>
)
}}
/>
<Tab.Screen
name="Settings"
component={SettingsScreen}
options={{
tabBarIcon: ({ color}) => (
<View style={{ flex: 1 }}>
<Feather name="settings" color={color} size={20} />
</View>
)
}}
/>
</Tab.Navigator>
)
}
I am currently using Expo to build my project.我目前正在使用 Expo 来构建我的项目。
My dependencies (package.json)我的依赖项(package.json)
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"@react-native-community/masked-view": "^0.1.5",
"@react-navigation/material-bottom-tabs": "^5.0.0",
"@react-navigation/native": "^5.0.0",
"@react-navigation/stack": "^5.0.0",
"@types/react-native": "^0.61.12",
"expo": "~36.0.0",
"react": "~16.9.0",
"react-dom": "~16.9.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-36.0.0.tar.gz",
"react-native-gesture-handler": "~1.5.0",
"react-native-paper": "^3.6.0",
"react-native-raw-bottom-sheet": "^2.0.6",
"react-native-reanimated": "~1.4.0",
"react-native-safe-area-context": "0.6.0",
"react-native-screens": "2.0.0-alpha.12",
"react-native-vector-icons": "^6.6.0",
"react-native-web": "~0.11.7"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"babel-preset-expo": "~8.0.0"
},
"private": true
}
I had almost the same issue with a tabnavigation as parent and stacknavigation as childs and rearranging my screen layer wasn't an option.我在 tabnavigation 作为父级和 stacknavigation 作为孩子时遇到了几乎相同的问题,并且重新排列我的屏幕层不是一个选项。 So I looked for another solution and from the docs I found out that the parent navigation UI is always shown on the child.
所以我寻找了另一种解决方案,从文档中我发现父导航 UI 总是显示在孩子身上。 But the docs also gave a great example on how to change a parent header from within a child.
但是文档还提供了一个很好的示例,说明如何从子项中更改父标题。 So I took that example and implemented it for the tabbar visibility.
所以我拿了这个例子并实现了它的标签栏可见性。 This is how I implemented it.
这就是我实现它的方式。
So I have a tabbar navigation with Home, Contacts and More, and inside each tab I have a stack.所以我有一个带有主页、联系人等的标签栏导航,在每个标签内我都有一个堆栈。 The screen that I hide the tabbar in is in the CameraView, and that screen is a stackscreen in the More tab.
我隐藏标签栏的屏幕在 CameraView 中,该屏幕是更多选项卡中的堆栈屏幕。
- Profile
轮廓
- CameraView (here I want to hide the tabbar)
CameraView(这里我想隐藏标签栏)
Tabnavigation:标签导航:
As you can see I get the visibility of the tabbar from a method.如您所见,我从一个方法中获得了标签栏的可见性。
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeNavigation} />
<Tab.Screen name="Contacts" component={ContactNavigation} />
<Tab.Screen
name="More"
component={MoreNavigation}
options={({ route }) => ({
tabBarVisible: this.getTabBarVisibility(route)
})}
/>
</Tab.Navigator>
</NavigationContainer>
Method getTabBarVisibility:方法 getTabBarVisibility:
This is were I check if the name of the route is CameraView which I defined in the StackNavigation.这是我检查路线的名称是否是我在 StackNavigation 中定义的 CameraView。
getTabBarVisibility = (route) => {
const routeName = route.state
? route.state.routes[route.state.index].name
: '';
if (routeName === 'CameraView') {
return false;
}
return true;
}
And the component MoreNavigation:和组件 MoreNavigation:
This is my stacknavigation for More, where you can see that the screen name is CameraView.这是我对 More 的堆栈导航,可以看到屏幕名称是 CameraView。
<Stack.Navigator initialRouteName="More">
<Stack.Screen name="More" component={More}/>
<Stack.Screen name="UserProfile" component={Profile}/>
<Stack.Screen name="CameraView" component={CameraView}/>
</Stack.Navigator>
You should try to rearrange your screen layer,你应该尝试重新排列你的屏幕层,
Original原来的
- TabBar
标签栏
- Pond(Stack)
池塘(堆叠)
- PondScreen
池塘屏风
- DetailScreen
详细画面
- Stock
库存
- Others
其他
Instead, try to set a top stack over相反,尝试设置顶部堆栈
- TopStack
顶栈
- TabBar
标签栏
- PondScreen
池塘屏风
- Stock
库存
- Others
其他
- Details
细节
That should be able to hide the bottom tab bar or tab header in each screen那应该能够隐藏每个屏幕中的底部标签栏或标签标题
The accepted answer is great, but you might want to do it inline, and use the getFocusedRouteNameFromRoute
to be safe.接受的答案很好,但您可能希望内联进行,并使用
getFocusedRouteNameFromRoute
以确保安全。 This code does the same as the accepted answer:此代码与接受的答案相同:
<Tabs.Screen
name="Home"
component={HomeStack}
options={({ route }) => ({
tabBarVisible: ((route) => {
const routeName = getFocusedRouteNameFromRoute(route) ?? ""
if (routeName === "CameraView") {
return false
}
return true
})(route),
})}
/>
The trick is to add the TabsStack, OtherStack or SomeOtherScreen inside your诀窍是将 TabsStack、OtherStack 或 SomeOtherScreen 添加到您的
<Stack.Navigator />
via a <Stack.Screen />
<Stack.Navigator />
通过<Stack.Screen />
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="TabsStack" component={TabsStack} />
<Stack.Screen name="SomeOtherScreen" component={SomeOtherScreen} />
<Stack.Screen name="OtherStack" component={OtherStack} />
</Stack.Navigator>
</NavigationContainer>
);
}
Add this function for hiding the bottom bar in MyTabBar在 MyTabBar 中添加隐藏底部栏的功能
const focusedOptions = descriptors[state.routes[state.index].key].options;
if (focusedOptions.tabBarVisible === false) {
return null;
}
MyTabBar我的标签栏
import { View, Text, TouchableOpacity } from 'react-native';
function MyTabBar({ state, descriptors, navigation }) {
const focusedOptions = descriptors[state.routes[state.index].key].options;
if (focusedOptions.tabBarVisible === false) {
return null;
}
return (
<View style={{ flexDirection: 'row' }}>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const onPress = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
};
const onLongPress = () => {
navigation.emit({
type: 'tabLongPress',
target: route.key,
});
};
return (
<TouchableOpacity
accessibilityRole="button"
accessibilityStates={isFocused ? ['selected'] : []}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarTestID}
onPress={onPress}
onLongPress={onLongPress}
style={{ flex: 1 }}
>
<Text style={{ color: isFocused ? '#673ab7' : '#222' }}>
{label}
</Text>
</TouchableOpacity>
);
})}
</View>
);
}
add bottom bar visibility in screen stack在屏幕堆栈中添加底部栏可见性
const getTabBarVisibility = (route) => {
const routeName = route.state
? route.state.routes[route.state.index].name
: '';
if (routeName === 'Profile') {
return false;
}
return true;
};
Add options in main tab navigators在主选项卡导航器中添加选项
const MainAppNavigator = ({userToken}) => {
return (
<NavigationContainer>
{!userToken ? (
<AuthNavigator />
) : (
<Tab.Navigator tabBar={(props) => <MyTabBar {...props} />}>
<Tab.Screen
name={'Dashboard'}
component={DashboardStackScreen}
/>
<Tab.Screen
name={'More'}
component={MoreStackScreen}
options={({route}) => ({
tabBarVisible: getTabBarVisibility(route),
})}
/>
</Tab.Navigator>
)}
</NavigationContainer>
);
};
Add Profile screen in More Stack在更多堆栈中添加配置文件屏幕
const MoreStack = createStackNavigator();
export default class MoreStackScreen extends React.Component {
render() {
return (
<MoreStack.Navigator initialRouteName={'More'}>
<MoreStack.Screen
name={'More'}
component={More}
/>
<MoreStack.Screen
name={'Profile'}
component={Profile}
/>
</MoreStack.Navigator>
);
}
}
You don't need to use Keyboard listeners and change your AndroidManifest.xml file you can solve this issue by just adding this tabBarOptions props :您不需要使用键盘侦听器并更改您的 AndroidManifest.xml 文件,只需添加此 tabBarOptions 道具即可解决此问题:
<Tab.Navigator
tabBarOptions={{
keyboardHidesTabBar: true,
}}>
</Tab.Navigator>
Tabbarvisible property didn't work for me and I made a small workaround. Tabbarvisible 属性对我不起作用,我做了一个小的解决方法。 It includes ReactContext + Hoc.
它包括 ReactContext + Hoc。
export const TabBarVisibilityContext = React.createContext({ visible: false, setVisible: () => { }, });
export const TabBarHidable = (Component) => (props) => { const [visible, setVisible] = useState(true); return ( <TabBarVisibilityContext.Provider value={{ visible, setVisible }}> <Component {...props} /> </TabBarVisibilityContext.Provider> ); };
const { visible, setVisible } = useContext(TabBarVisibilityContext);
Update properties in tab navigator options tabBarOptions = {{ style: { transform: !visible ?更新选项卡导航器选项中的属性 tabBarOptions = {{ style: { transform: !visible ? [{ scale: 0 }] : [], }}
[{ scale: 0 }] : [], }}
Use setVisible from context to make the tabbar hidden.使用上下文中的 setVisible 隐藏标签栏。
const { setVisible } = useContext(TabBarVisibilityContext); useEffect(() => { setVisible(false); return () => setVisible(true); , []})
Hope it will help someone to save his/her time.希望它会帮助某人节省他/她的时间。 I haven't found an appropriate and concise solution to the given problem.
我还没有找到针对给定问题的适当且简洁的解决方案。
I am using typescript and I encountered such an issue too.我正在使用打字稿,我也遇到了这样的问题。 Since the tabBarVisible option is no longer available, I used the tabBarStyle instead and set the display property to 'none'.
由于 tabBarVisible 选项不再可用,我改用 tabBarStyle 并将显示属性设置为“无”。
Suppose I have two screens, the Home screen which is the tabbed screen and another screen say Side screen which is a Stacked screen where I want to hide the tab bar, then I do this in the Stacked screen navigator component:假设我有两个屏幕,主屏幕是选项卡式屏幕,另一个屏幕说侧屏幕是我想隐藏标签栏的堆叠屏幕,然后我在堆叠屏幕导航器组件中执行此操作:
const setTabStyleVisibility = (shouldBeVisible: boolean) =>
shouldBeVisible
? ({
tabBarStyle: { display: 'flex' },
} as Partial<BottomTabNavigationOptions>)
: ({
tabBarStyle: { display: 'none' },
} as Partial<BottomTabNavigationOptions>);
I have a custom button defined as:我有一个自定义按钮定义为:
<Button title={btnTitle} onPress={onPressHandler}/>
On the Home Screen, I have a button which navigates to the Side screen and hides the tab by defining the custom onPressedHandler prop to the custom button as:在主屏幕上,我有一个按钮可以导航到侧屏幕并通过将自定义 onPressedHandler 属性定义为自定义按钮来隐藏选项卡:
onPressHandler={() => {
navigation.setOptions({
...setTabStyleVisibility(false),
});
navigation.navigate("Side");
}}
Then I had a button passed to the next screen (Side screen) where the tab bar will be shown on going back to Home screen.然后我有一个按钮传递到下一个屏幕(侧屏),在返回主屏幕时将显示标签栏。 I set the onPressedHandler which is a custom prop to the custom button to
我将作为自定义道具的 onPressedHandler 设置为自定义按钮
onPressHandler={() => {
navigation.setOptions({
...setTabStyleVisibility(true),
});
navigation.navigate("Home");
}}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.