如何在 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 或其他按钮。
使用另一个导航器包裹 AuthStackNavigation
和 DrawerNavigation
。
使用 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中也有解释。
我正在做一个像 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 或其他按钮。
使用另一个导航器包裹 AuthStackNavigation
和 DrawerNavigation
。
使用 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中也有解释。