0

I am new to react native development, but i have some requirement with react navigation drawer. I want to display the navigation drawer from top of the screen but it is display below from toolbar. It is a combination of both Stack and Drawer screens. Following is my code in App.js

function App() {
  SplashScreen.hide()
  return (
    <NavigationContainer>
      {/* headerMode='float' */}
      <Stack.Navigator initialRouteName='Login' >
        <Stack.Screen name="Login" component={LoginScreen}
          options={{ headerShown: false }} />
        {/* <Stack.Screen name="Home" component={HomeScreen} /> */}
        <Stack.Screen name="DrawerScreens" component={DrawerScreens} 
          options={({ navigation, route }) => ({
            title: "Home",
            headerTintColor: '#FFFFFF', headerStyle:{backgroundColor:'#154493'},
            headerLeft: props => <NavigationDrawerStructure navObj={navigation} />,
          })} />

        <Stack.Screen name="Dashboard" component={Dashboard} 
            options={({ route }) => ({headerTintColor: '#FFFFFF', headerStyle:{backgroundColor:'#154493'}})} />
</Stack.Navigator>
</NavigationContainer>

DrawerScreens function is like following..

function DrawerScreens({ route, navigation }) {
  // console.log("param:"+route.params.token)
  return (
    //drawerContent={props=>CustomDrawerContent(props)}
    // <SafeAreaProvider>

    <Drawer.Navigator drawerContent={props => CustomDrawerContent(props)} headerMode="float" >
    {/* <Drawer.Navigator drawerContent={props => CustomDrawerContent(props)}> */}
      {/* options={{ drawerLabel: 'Updates' }} */}

      <Drawer.Screen name="LandingScreen" component={LandingScreen}
        initialParams={{ token: route.params.token }}/>
  );
}

CustomDrawer function contains list of the menu items which is dynamic and NestedMenuView is taking care of that..

function CustomDrawerContent(props) {
  return (
 <SafeAreaView style={{flex: 1}} forceInset={{ top: "always" }}>

      <NestedMenuView navObj={props.navigation} />

      </SafeAreaView>       

  );
};

Please check the reference image here, I want left menu starts from header instead of below from header

For me the combination of both stack and drawer screens.Thanks in advance.

malli
  • 642
  • 2
  • 12
  • 30
  • I don't see anything in you're code, but if this can help, I make drawer with react navigation v5, you can check the code : https://github.com/samuel3105/react-native-navigation – samuel May 12 '20 at 20:19

3 Answers3

0

I don't think the problem lies around the Stack Navigator or the Screen components;

If you use the latest, after v5 release version of @react-navigation/drawer (mine is 5.6.3) the recommended way is to use the built-in wrappers when creating custom drawer

const Drawer = createDrawerNavigator();

const Menu = (props) => {
  return (
    <DrawerContentScrollView {...props}>
      <DrawerItemList {...props} />
      <DrawerItem label="Help" onPress={() => {}} />
    </DrawerContentScrollView>
  );
};

export default function MyDrawer() {
  return (
    <Drawer.Navigator
      initialRouteName="Tabs"
      drawerContent={(props) => <Menu {...props} />}
      edgeWidth={100}
      drawerContentOptions={{
        activeTintColor: Colors.accentColor,
        labelStyle: {
          fontFamily: 'open-sans',
        },
      }}
    >
      <Drawer.Screen...
    </Drawer.Navigator>
  );

You can also leave the scrollview and create custom ui like this:


const contentOptions = {
    activeBackgroundColor: '#dbdbdb',
    activeLabelStyle: {
        fontSize: 16,
        color: 'black',
        fontFamily: 'roboto'
    },
    labelStyle: {
        fontSize: 16,
        fontWeight: 'normal',
        color: intenseGrey,
        fontFamily: 'roboto'
    }
};

    return (
        <View
            style={{
                display: 'flex',
                flexDirection: 'column',
                flexGrow: 1
            }}
        >
            <SafeAreaView style={{ flex: 1, paddingBottom: 0 }}>
                <View style={{
                    backgroundColor: '#dbdbdb',
                    display: 'flex',
                    flexDirection: 'column',
                    justifyContent: 'space-between',
                    flexGrow: 1}}
                 >
                    <View>
                        <DrawerItemList {...props} {...contentOptions} />
                    </View>
                </View>
            </SafeAreaView>
        </View>
    );
  • Thanks MR.Bence Rozsa for giving quick response. If i have single level list then the above solution will work i guess. But i want the menu list will be multi level means when i click on the item it opens other list inside it upto 2 levels. So that purpose i used 'NestedMenuView'..Can you please look in such a way and let me know if you have any other.. – malli May 12 '20 at 16:57
  • Sure, I understand now. I haven't done multi-level drawer navigation, although @gie3d is surely right about using drawer on the top, and nest everything below that. – Bence Rozsa May 13 '20 at 06:16
0

I think the reason that Drawer is not covering is because you put the Drawer navigation inside your Stack navigation.

Yours

Stack
   Drawer

To fixed that you have to readjust the order

Drawer
    Stack

For example (or you could see from my snack here: https://snack.expo.io/@gie3d/d25aca)

const HomeStack = () => (
  <Stack.Navigator>
    <Stack.Screen name="Home" component={Home} options={({navigation}) => ({
      title: "Home",
      headerLeft: () => (
          <Ionicons
            name={'md-menu'}
            size={24}
            style={{ marginLeft: 10 }}
            onPress={() =>
              navigation.dispatch(DrawerActions.toggleDrawer())
            }
          />
        ),
    })} />
  </Stack.Navigator>
);

const Home = () => {
  return (
  <View>
    <Text>This is Home</Text>
  </View>
)}

export default () => {
  return (
    <NavigationContainer>
      <Drawer.Navigator initialRouteName="HomeStack">
        <Drawer.Screen name="HomeStack" component={HomeStack} />
        <Drawer.Screen name="HomeNoStack" component={Home} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}
gie3d
  • 766
  • 4
  • 8
  • Thanks for the quick response MR.gie3d. I used your technique with two of the screens login,landing screens but showing navigation drawer in login screen too. How can i avoid that to display with login screen.please help me out.. – malli May 13 '20 at 07:37
  • updated the code in app.js is {/* */} – malli May 13 '20 at 07:40
  • 1
    I think this is what you are looking for, https://reactnavigation.org/docs/auth-flow. The idea is to have separate Navigators for Login and other After Login. – gie3d May 13 '20 at 08:20
  • Not sure, but i want it to be work like following.1.Loginscreen doesn't show navigation drawer 2. Once i login i need it should show from top of the screen. – malli May 13 '20 at 08:40
  • I need the combination of both screens even after login @gie3d. – malli May 13 '20 at 11:55
  • Yes, you can see how to implement from the link i sent you above (auth flow) – gie3d May 13 '20 at 12:05
  • How can i mention both stack and drawer screens in app.js after login?? – malli May 13 '20 at 12:21
0

The following stacks created and calling these stacks from Drawer Screens.

const LandingStack = ({ route, navigation }) => (
  <Stack.Navigator>
    <Stack.Screen name="LandingScreen" component={LandingScreen} options={({navigation}) => ({
      headerTitle: 'Home',
      headerTintColor: '#FFFFFF', headerStyle:{backgroundColor:'#000' },
      headerLeft: props => <NavigationDrawerStructure navObj={navigation} />,
    })} />
  </Stack.Navigator>
);

const TicketingStack = () => (
  <Stack.Navigator>
    <Stack.Screen name="TicketingDashboard" component={TicketingDashboard} options={({route, navigation}) => ({
      headerTitle: route.params.type,
      headerTintColor: '#FFFFFF', headerStyle:{backgroundColor:'#000' },
      headerLeft: props => <NavigationDrawerStructure navObj={navigation} />,
    })} />
  </Stack.Navigator>
);


function DrawerScreens({ route, navigation }) {
  // console.log("param:"+route.params.token)
  return (
    //drawerContent={props=>CustomDrawerContent(props)}
    <SafeAreaProvider>

    <Drawer.Navigator drawerContent={props => CustomDrawerContent(props)} headerMode="screen">


      {/* options={{ drawerLabel: 'Updates' }} */}

      {/* <Stack.Screen name="DrawerScreens" component={DrawerScreens}
          options={({ navigation, route }) => ({
            title: "Home",
            headerTintColor: '#FFFFFF', headerStyle:{backgroundColor:'#000' },
            headerLeft: props => <NavigationDrawerStructure navObj={navigation} />,
          })} /> */}

      <Drawer.Screen name="LandingStack" component={LandingStack}

        initialParams={{ token: route.params.token }}/>

      <Drawer.Screen name="HomeStack" component={HomeStack}
        initialParams={{ token: route.params.token }} />
    </Drawer.Navigator>

    </SafeAreaProvider>
  );
}

And I have removed header part from the function App and finally looks like this in the App.js

 <Stack.Screen name="DrawerScreens" component={DrawerScreens}
          options={{ headerShown: false }} />
malli
  • 642
  • 2
  • 12
  • 30
  • My answer helps to someone who are using same architecture and facing the same issue.Thanks everyone for giving the inputs to solve the issue. – malli May 19 '20 at 12:12