Je voulais savoir comment masquer la barre d'onglets inférieure d'un écran spécifique dans mon navigateur de pile qui est imbriquée dans une barre d'onglets inférieure de matériau
Ceci est mon code pour mon navigateur de pile
{ "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 }
Ceci est mon code pour mon navigateur d'onglet inférieur matériel
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> ) }
J'utilise actuellement Expo pour construire mon projet.
Mes dépendances (package.json)
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> ); }
5 Réponses :
Vous devriez essayer de réorganiser votre calque d'écran,
Original
- Barre d'onglets
- Étang (pile)
- PondScreen
- DetailScreen
- Stock
- Autres
Au lieu de cela, essayez de placer une pile supérieure sur
- TopStack
- Barre d'onglets
- PondScreen
- Stock
- Autres
- Détails
Cela devrait pouvoir masquer la barre d'onglets inférieure ou l'en-tête de l'onglet dans chaque écran
Cela devrait être la réponse acceptée car c'est celle recommandée par la documentation.
Une idée comment faire avec cela avec plusieurs piles? Une autre pile après avoir navigué via l'onglet?
Si vous avez des piles imbriquées, placez-les simplement dans la pile la plus basse. C'est comme ça que ça a fonctionné pour moi. Là, j'ai remplacé le composant d'accueil par le nav TabBar.
J'ai eu presque le même problème avec une tabnavigation en tant que parent et stacknavigation en tant qu'enfant et la réorganisation de ma couche d'écran n'était pas une option. J'ai donc cherché une autre solution et à partir des documents, j'ai découvert que l'interface utilisateur de navigation parentale était toujours affichée sur l'enfant. Mais la documentation a également donné un excellent exemple sur la façon de modifier un en-tête parent à partir d'un enfant. J'ai donc pris cet exemple et l'ai implémenté pour la visibilité de la barre d'onglets. C'est ainsi que je l'ai implémenté.
J'ai donc une barre d'onglets de navigation avec Accueil, Contacts et plus, et à l'intérieur de chaque onglet, j'ai une pile. L'écran dans lequel je cache la barre d'onglets se trouve dans CameraView, et cet écran est un écran de pile dans l'onglet Plus.
- Profil
- CameraView (ici je veux cacher la barre d'onglets)
Tabnavigation:
Comme vous pouvez le voir, j'obtiens la visibilité de la barre d'onglets à partir d'une méthode.
<Stack.Navigator initialRouteName="More"> <Stack.Screen name="More" component={More}/> <Stack.Screen name="UserProfile" component={Profile}/> <Stack.Screen name="CameraView" component={CameraView}/> </Stack.Navigator>
Méthode getTabBarVisibility:
C'est là que je vérifie si le nom de la route est CameraView que j'ai défini dans StackNavigation.
getTabBarVisibility = (route) => { const routeName = route.state ? route.state.routes[route.state.index].name : ''; if (routeName === 'CameraView') { return false; } return true; }
Et le composant MoreNavigation:
Ceci est ma stacknavigation pour Plus, où vous pouvez voir que le nom d'écran est CameraView.
<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>
@BoyPasmo Heureux que je puisse vous aider!
La documentation recommande de ne pas utiliser cette approche car elle provoquera des animations glitchy avec le composant de pied de page. Je recommanderais de ne pas utiliser cette approche et de réorganiser vos pages comme le suggère la documentation.
@EricWiener la documentation a été récemment mise à jour, j'ai donné cette réponse avant que la documentation ne soit mise à jour. Nous n'avons rencontré aucun problème dans notre application. Pour cela, nous nous en tenons à cette solution et ne réorganiserons pas nos pages, alors qu'il est étrange d'avoir une pile supplémentaire que vous n'utilisez pas, uniquement pour cacher un bottombar. Au fait, ils suggèrent cette approche si vous souhaitez définir l'en-tête différemment ....
@Emmie l'a compris. Merci de me le faire savoir. Votre réponse fait définitivement le travail, mais pour moi, cela faisait disparaître la barre d'onglets trop tôt avant de naviguer vers une nouvelle page.
@EricWiener Bon à savoir, lorsque nous avons des problèmes de pépin, nous nous pencherons sur cela.
@EricWiener merci de son travail mais il montre un espace blanc en bas lorsque je cache l'onglet du bas dans nextscreen. Quelqu'un a quelquonque idée.
@pragnesh J'ai fini par avoir le même problème lors de l'utilisation d'un onglet inférieur avec une vue Accessoire clavier. Je cache la barre d'onglets sur l'écran qui posait problème et j'affiche un composant de barre d'onglets identique en tant qu'enfant de cet écran
Cela a fonctionné pour moi lors de la transition vers une WebView qui a pris en charge la vue entière, mais lorsque l'utilisateur glisse pour revenir en arrière, cela a un peu changé l'animation: /
"tabBarVisible" n'est pas disponible dans createMaterialBottomTabNavigator, donc cela ne fonctionne pas!
@AdamRi n'est pas disponible pour createMaterialBottomTabNavigator spécifique. Cela fonctionne donc pour l'utilisateur qui a posé la question, mais cela ne fonctionne pas pour le fond de matériau spécifique.
L'astuce consiste à ajouter TabsStack, OtherStack ou SomeOtherScreen dans votre
<Stack.Navigator />
via un <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> ); }
c'est documenté ici
Merci Luke. Bonne réponse avec un exemple de code dedans et ça marche
J'avais l'habitude d'avoir ceci sur Navigation4.x mais dans 5, tout est comme neuf, donc cela me manque. Ça marche
Merci, c'est la meilleure solution, vous pouvez afficher uniquement l'en-tête TabsStack et masquer le "Stack.Screen" en utilisant options = {{headerShown: false}} comme ceci: <Stack.Screen name = "TabsStack" component = {TabsStack} options = {{headerShown: false}} />
Ajoutez cette fonction pour masquer la barre inférieure dans MyTabBar
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> ); } }
MyTabBar
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> ); };
ajouter la visibilité de la barre inférieure dans la pile d'écran
const getTabBarVisibility = (route) => { const routeName = route.state ? route.state.routes[route.state.index].name : ''; if (routeName === 'Profile') { return false; } return true; };
Ajouter des options dans les navigateurs des onglets principaux
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> ); }
Ajouter un écran de profil dans More Stack
const focusedOptions = descriptors[state.routes[state.index].key].options; if (focusedOptions.tabBarVisible === false) { return null; }
Cela fonctionne aussi. Merci
La réponse acceptée est excellente, mais vous voudrez peut-être le faire en ligne et utiliser getFocusedRouteNameFromRoute
pour être sûr. Ce code fait la même chose que la réponse acceptée:
<Tabs.Screen name="Home" component={HomeStack} options={({ route }) => ({ tabBarVisible: ((route) => { const routeName = getFocusedRouteNameFromRoute(route) ?? "" if (routeName === "CameraView") { return false } return true })(route), })} />
J'ai essayé cela et cela fonctionne. C'est vraiment une alternative en ligne
Pour votre prochaine question, vous souhaiterez peut-être marquer votre question avec React-navigation afin que davantage de personnes puissent la voir.