如何在 React Navigation 中添加 Drawer Inside Stack Navigation

How to add a Drawer Inside Stack Navigation in React Navigation

我正在做一个像 Login/Register 应用程序这样的练习项目,我正在使用 react-navigations 的 Stack Navigation,它工作得很好,

现在,当用户登录时,他应该被重定向到仪表板屏幕,其中 我想要一个抽屉到 header "I also added a screenshot" 的右侧,我在 Stack Navigation 中也创建了 Dashboard Screen 我不知道如何在 Stack Navigation 中添加那个抽屉谢谢

App.js(我添加了所有 Stack Screens)

    import React from 'react';

    import { createStackNavigator, createDrawerNavigator } from 'react-navigation';

    import HomeScreen from './screens/HomeScreen';
    import LoginScreen from './screens/LoginScreen';
    import RegisterScreen from './screens/RegisterScreen';
    import Dashboard from './screens/Dashboard';

    const StackNavigation = createStackNavigator({
      HomeStack: HomeScreen,
      LoginStack: LoginScreen,
      RegisterStack: RegisterScreen,
      DashboardStack: Dashboard,

    }, {
        initialRouteName: 'HomeStack',
      });

      const DrawerNav = createDrawerNavigator({
        DashboardStack: Dashboard,
      })


    export default class App extends React.Component {
      render() {
        return (
          <StackNavigation />
        );
      }
    }

Dashboard.js

    import React from 'react';
    import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';

    import Icon from 'react-native-vector-icons/FontAwesome';

    export default class Dashboard extends React.Component {

        static navigationOptions = {

            headerTitle: 'Dashboard',
            headerLeft: null,

            headerTitleStyle: {
                flex: 1,
                color: '#fff',
                textAlign: 'center',
                alignSelf: 'center',
                fontWeight: 'normal',
            },

            headerStyle: {
                backgroundColor: '#b5259e',
            },
        }

显示右侧的抽屉。

创建抽屉导航器时添加drawer Position参数。

const DrawerNav = createDrawerNavigator({
  DashboardStack: Dashboard, 
},
{
  drawerPosition: 'right'
});

从 header 的按钮调用 DrawerNavigation。

Dashboard.js 中为 toggleDrawer 添加一个按钮到 header。您可以在 navigationOptions;

中获取如下导航实例

class Dashboard extends React.Component {
  static navigationOptions = ({navigation, navigationOptions}) => {
    return {
      headerTitle: 'Dashboard@@',
      headerLeft: <Text>Left</Text>,
      headerRight: (
        <Button onPress = {navigation.toggleDrawer}
        title="Menu"
        color="#fff">
          <Text>Menu</Text>
        </Button>
      ),
      headerTitleStyle: {
        flex: 1,
        color: '#fff',
        textAlign: 'center',
        alignSelf: 'center',
        fontWeight: 'normal',
      },

      headerStyle: {
        backgroundColor: '#b5259e',
      },
    }
  }

您可以将按钮更改为 Touchable Opacity 或其他按钮。

使用另一个导航器包裹 AuthStackNavigationDrawerNavigation

使用 createSwitchNavigation 或其他方法包装您的导航并导出。

// App.js

import React from 'react';

import {
  createStackNavigator,
  createDrawerNavigator,
  createSwitchNavigator,
} from 'react-navigation';

import HomeScreen from './srcs/screens/Home';
import Dashboard from './srcs/screens/Dashboard';

const AuthStackNavigation = createStackNavigator({
  HomeStack: HomeScreen,
  LoginStack: HomeScreen,
  RegisterStack: HomeScreen,
}, {
  initialRouteName: 'HomeStack',
})

const DashboardStack = createStackNavigator({ // For header options
  Dashboard: Dashboard
})

const DrawerNav = createDrawerNavigator({
  DashboardStack: DashboardStack,
  SecondScreen: Dashboard, // You should use another screen.
  ThirdScreen: Dashboard,
})

const MainNavigation = createSwitchNavigator({
  HomeDrawer: DrawerNav,
  AuthStack: AuthStackNavigation, // You will use this.props.navigation.replace('HomeDrawer') after login process.
})

export default MainNavigation // Stack, Drawer, Switch naviagtions return react component.

我刚刚创建了一个可能是您需要的示例。

import React, {Component} from 'react';
import {
  StyleSheet,
  Button,
  Image,
  TouchableWithoutFeedback,
  View,
} from 'react-native';
import {
  createDrawerNavigator,
  createStackNavigator,
  StackActions,
  NavigationActions,
} from 'react-navigation';


class HomeScreen extends React.Component {
  render() {
    return (
        <View style={styles.container}>
          <Button
              onPress={() => this.props.navigation.navigate('Notifications')}
              title="Go to notifications"
          />
        </View>
    );
  }
}

class NotificationsScreen extends React.Component {
  render() {
    return (
        <View style={styles.container}>
          <Button
              onPress={() => this.props.navigation.navigate('Home')}
              title="Go back home"
          />
        </View>
    );
  }
}

class LoginScreen extends Component {
  openDashboard = () => {
    const resetAction = StackActions.reset({
      index: 0,
      actions: [NavigationActions.navigate({routeName: 'Dashboard'})],
    });
    this.props.navigation.dispatch(resetAction);
  }

  render() {
    return (
        <View style={styles.container}>
          <Button
              onPress={this.openDashboard}
              title={'Login'}
          />
        </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingHorizontal: 20,
  },
  icon: {
    width: 24,
    height: 24,
  },
  menu: {
    marginRight: 8,
  }
});

const renderMenu = (navigation) => (
    <TouchableWithoutFeedback onPress={() => navigation.openDrawer()}>
      <Image
          source={require('./menu.png')}
          style={[styles.icon, styles.menu]}
      />
    </TouchableWithoutFeedback>
)

const Home = createStackNavigator({
  Home: {
    screen: HomeScreen,
    navigationOptions: ({navigation}) => ({
      title: 'Home',
      headerRight: renderMenu(navigation)
    }),
  }
})

const Notifications = createStackNavigator({
  Notifications: {
    screen: NotificationsScreen,
    navigationOptions: ({navigation}) => ({
      title: 'Notifications',
      headerRight: renderMenu(navigation)
    })
  }
})

const Dashboard = createDrawerNavigator(
    {
      Home: {
        screen: Home,
        navigationOptions: {
          drawerLabel: 'Home',
          drawerIcon: (
              <Image
                  source={require('./chats-icon.png')}
                  style={styles.icon}
              />
          ),
        }
      },
      Notifications: {
        screen: Notifications,
        navigationOptions: {
          drawerLabel: 'Notifications',
          drawerIcon: (
              <Image
                  source={require('./notif-icon.png')}
                  style={styles.icon}
              />
          ),
        }
      },
    },
    {
      drawerPosition: 'right'
    }
);

const App = createStackNavigator(
    {
      Login: LoginScreen,
      Dashboard: Dashboard
    },
    {
      initialRouteName: 'Login',
      headerMode: 'none'
    }
)

export default App;
  • 当用户按下 LoginScreen 上的登录按钮时,导航将被重置(这样用户就无法通过 android 上的后退箭头或物理后退按钮返回登录屏幕)。
  • 然后我们在右边创建一个抽屉,有两个屏幕和一个汉堡包图标。
  • 主页的子屏幕应该在主页堆栈内,通知也是如此。

您只需添加缺少的图标即可。

对于那些在 react-navigation 5.X 中寻找解决方案的人,您可以这样做:

抽屉导航器

const ProductListWithDrawer = () => {
 return (
  <Drawer.Navigator initialRouteName="ProductList">
   <Drawer.Screen name="ProductList" component={screens.ProductList} />
   <Drawer.Screen name="ProductDetail" component={screens.ProductDetailScreen} />
  </Drawer.Navigator>
  );
 };

Stack Navigator(应该包裹在 Navigation Container

<Stack.Navigator initialRouteName="Dashboard" screenOptions={{ headerShown: false }}>
  <Stack.Screen name="Dashboard" component={screens.Dashboard} />
  <Stack.Screen name="Loading" component={screens.Loading} />
  <Stack.Screen name="Chat" component={screens.Chat} />
  <Stack.Screen name="ProductListWithDrawer" component={ProductListWithDrawer} /> //our drawer
</Stack.Navigator>

基本上,这应该可以完成工作。还有一件事可能是这里的问题,即在使用参数导航到抽屉导航器内的那些屏幕时。在这种情况下,可以这样做:

navigation.navigate("ProductListWithDrawer", {
              screen: "ProductList",
              params: { user: "Alex"},
            });

这在Nesting navigators中也有解释。