React Native 不嵌套同时使用DrawerNavigator与TabsNavigator实现方案
解决方案
核心实现思路
你想要的两个导航器全局可见、共用屏幕实例的需求,可以通过 Drawer嵌套Tabs + 劫持Drawer菜单项跳转逻辑 实现,完全不需要在两个导航器中重复声明屏幕,也不会生成重复的屏幕实例。
具体逻辑如下:
- 把整个Tabs导航器作为Drawer导航器的唯一子屏幕
- 自定义Drawer的内容列表,点击Drawer里的菜单项时,直接调用Tab导航的
jumpTo方法切换对应Tab,而不是跳转Drawer自身的屏幕
该方案下不管切换到哪个Tab,外层的Drawer始终可以呼出,内层的Tab也始终固定展示,所有屏幕都是Tabs中声明的实例,不会重复创建。
完整代码实现
1. 自定义Drawer内容,劫持跳转逻辑
import { DrawerContentScrollView, DrawerItem } from '@react-navigation/drawer'; const CustomDrawerContent = (props) => { // 获取内层Tab导航的实例 const tabNavigation = props.navigation.getParent('TabNavigator'); // 你的所有页面名,和Tabs中声明的name保持一致即可 const screenList = ['Calendar', 'Reminders', 'Weather']; return ( <DrawerContentScrollView {...props}> {screenList.map(screenName => ( <DrawerItem key={screenName} label={screenName} onPress={() => { // 点击后直接切换Tab,不触发Drawer的页面跳转 tabNavigation.jumpTo(screenName); // 切换完成后关闭抽屉 props.navigation.closeDrawer(); }} /> ))} </DrawerContentScrollView> ); };
2. 改造DrawerNavigator,仅保留Tabs作为唯一子页面
const Drawer = createDrawerNavigator(); function DrawerNavigator() { return ( <Drawer.Navigator drawerContent={(props) => <CustomDrawerContent {...props} />} // 隐藏Drawer默认头部,使用页面自定义头部或者Tab头部即可 screenOptions={{ headerShown: false }} > {/* 唯一子页面就是整个Tab导航器 */} <Drawer.Screen name="TabsContainer" component={TabsNavigator} options={{ title: '首页' }} /> </Drawer.Navigator> ); } export default DrawerNavigator
3. 给TabsNavigator添加id标识,方便外层获取实例
const Tabs = createMaterialTopTabNavigator(); const TabsNavigator = () => { return ( {/* 此处id和自定义Drawer中getParent的参数保持一致即可 */} <Tabs.Navigator id="TabNavigator"> <Tabs.Screen name="Calendar" component={Calendar} /> <Tabs.Screen name="Reminders" component={Reminders} /> <Tabs.Screen name="Weather" component={Weather} /> </Tabs.Navigator> ); }; export default TabsNavigator;
4. 改造App.js入口代码
export default function App() { return ( <NavigationContainer> <DrawerNavigator /> </NavigationContainer> ); }
内容的提问来源于stack exchange,提问作者Royal
相关产品推荐
相关产品推荐

