DrawerNavigator to show tab bar all the time with every option tapped

3.4k views Asked by At

I am trying to have a tab bar and each tab bar has its own stack navigator. Three tabs that i have are Home Profile Settings

I want to show these three options in the drawer also. I have created a drawer but only tapping home shows the tab bar. I want to show tab bar just like if you press of profile tab and tab bar remains there.

Tabs with their stack navigators

Side drawer with same options

Tapping profile from drawer hides tab bar

Here is my code:

const HomeStackNavigator = createStackNavigator();
export const HomeNavigator = () => {
  return (
    <HomeStackNavigator.Navigator screenOptions={defaultNavOptions}>
      <HomeStackNavigator.Screen
        name="Home"
        component={HomeScreen}
        options={homeScreenOptions}
      />
       <HomeStackNavigator.Screen
        name="Details"
        component={DetailsScreen}
        options={detailsScreenOptions}
      />
    </HomeStackNavigator.Navigator>
  );
};

const ProfileStackNavigator = createStackNavigator();
export const ProfileNavigator = () => {
  return (
    <ProfileStackNavigator.Navigator screenOptions={defaultNavOptions}>
      <ProfileStackNavigator.Screen
        name="Profile"
        component={ProfileScreen}
        options={profileScreenOptions}
      />
       <ProfileStackNavigator.Screen
        name="EditProfile"
        component={EditProfileScreen}
        options={editProfileScreenOptions}
      />
    </ProfileStackNavigator.Navigator>
  );
};

const SettingsStackNavigator = createStackNavigator();
export const SettingsNavigator = () => {
  return (
    <SettingsStackNavigator.Navigator screenOptions={defaultNavOptions}>
      <SettingsStackNavigator.Screen
        name="Settings"
        component={SettingsScreen}
        options={settingsScreenOptions}
      />
       <SettingsStackNavigator.Screen
        name="AccountDetail"
        component={AccountDetailsScreen}
        options={accountDetailsScreenOptions}
      />
    </SettingsStackNavigator.Navigator>
  );
};




const HomeTabNavigator = createBottomTabNavigator();
export const TabNavigator = () => {
  return (
    <HomeTabNavigator.Navigator screenOptions={defaultNavOptions}>
      <HomeTabNavigator.Screen
        name="Home"
        component={HomeNavigator}
        options={{
          tabBarLabel: 'Home',
          tabBarIcon: ({ color, size }) => (
            <MaterialCommunityIcons name="home" color={color} size={size} />
          ),
        }}
      />
       <HomeTabNavigator.Screen
        name="Profile"
        component={ProfileNavigator}
        options={{
          tabBarLabel: 'Profile',
          tabBarIcon: ({ color, size }) => (
            <MaterialCommunityIcons name="face-profile" color={color} size={size} />
          ),
        }}
      />
      <HomeTabNavigator.Screen
        name="Settings"
        component={SettingsNavigator}
        options={{
          tabBarLabel: 'Settings',
          tabBarIcon: ({ color, size }) => (
            <MaterialCommunityIcons name="account-settings" color={color} size={size} />
          ),
        }}
      />
    </HomeTabNavigator.Navigator>
  );
};



const AppDrawer = createDrawerNavigator();
export const Drawer = () => {
  return(
      <AppDrawer.Navigator initialRouteName="Home">
        <AppDrawer.Screen name="Home" component={TabNavigator} />
        <AppDrawer.Screen name="Profile" component={ProfileNavigator} />
        <AppDrawer.Screen name="Settings" component={SettingsNavigator} />
      </AppDrawer.Navigator>
  )
};

My goal is to have tabs all the time. Tabs should hide only if we go to the detail page of any of the tabs.

1

There are 1 answers

1
bas On BEST ANSWER

You can make your TabNavigator a screen of a stack navigator which is a screen of your drawer navigator and pass a custom drawer component to your drawer navigator:

const AppDrawer = createDrawerNavigator();
const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();
const HomeTabNavigator = createBottomTabNavigator();

export const TabNavigator = () => {
  return (
    <HomeTabNavigator.Navigator>
      <HomeTabNavigator.Screen
        name="Home"
        component={HomeScreen}
        options={{
          tabBarLabel: 'Home',
        }}
      />
      <HomeTabNavigator.Screen
        name="Profile"
        component={ProfileScreen}
        options={{
          tabBarLabel: 'Profile',
        }}
      />
      <HomeTabNavigator.Screen
        name="Settings"
        component={SettingsScreen}
        options={{
          tabBarLabel: 'Settings',
        }}
      />
    </HomeTabNavigator.Navigator>
  );
};

function CustomDrawerContent(props) {
  return (
    <DrawerContentScrollView {...props}>
      <DrawerItem
        label="Home"
        onPress={() => props.navigation.navigate('Home')}
      />
      <DrawerItem
        label="Profile"
        onPress={() => props.navigation.navigate('Profile')}
      />
      <DrawerItem
        label="Settings"
        onPress={() => props.navigation.navigate('Settings')}
      />
    </DrawerContentScrollView>
  );
}

function getHeaderTitle(route) {
  return getFocusedRouteNameFromRoute(route) ?? 'Home';
}

const StackNavigator = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Tabs"
        component={TabNavigator}
        options={({route}) => ({
          headerTitle: getHeaderTitle(route),
        })}
      />
      <Stack.Screen name="EditProfile" component={EditProfileScreen} />
      <Stack.Screen name="Details" component={DetailsScreen} />
      <Stack.Screen name="AccountDetail" component={AccountDetailsScreen} />
    </Stack.Navigator>
  );
};

export const Drawer = () => {
  return (
    <AppDrawer.Navigator
      initialRouteName="Home"
      drawerContent={(props) => <CustomDrawerContent {...props} />}>
      <AppDrawer.Screen name="Stack" component={StackNavigator} />
    </AppDrawer.Navigator>
  );
};

function App() {
  return (
    <NavigationContainer>
      <Drawer />
    </NavigationContainer>
  );
}

The screens you don't want to show the tabs for can be put inside the stack navigator outside of the tab navigator.


Sources:

Be sure to import DrawerItem, DrawerContentScrollView from @react-navigation/drawer and getFocusedRouteNameFromRoute from @react-navigation/native.