使用堆栈中的外部屏幕正确嵌套底部选项卡

Posted

技术标签:

【中文标题】使用堆栈中的外部屏幕正确嵌套底部选项卡【英文标题】:Proper nesting bottom tab with external screen from stack 【发布时间】:2021-08-08 02:34:19 【问题描述】:

我正在使用 react-native 0.64 和 react-navigation v5 构建一个应用程序。

我正在尝试实现一个导航结构,顶部有一个抽屉,一个带有按钮的 HomeScreen(没有底部标签)导航到 5 个屏幕 - 那些有底部标签的屏幕 - 和一个带有 6 个标签的 BottomTab:相同的 5 个屏幕(每个它们允许导航到不同的子屏幕)和主屏幕的选项卡

根据 react-navigation 文档 (Hiding tab bar in specific screens),在我的实现中,我避免使用“tabBarVisible”道具,而是将 HomeScreen 放在父 Stack 中,而 BottomTab 是它的屏幕之一。问题是我想在 BottomTab 中有一个 HomeScreen 选项卡,即使此屏幕不在 BottomTab 内(当用户按下 Home 选项卡时,应用程序应该导航到不再显示 BottomTab 的 HomeScreen) .

我尝试实现的是这样的结构:

[抽屉] [主堆栈] 主屏幕 [底部选项卡] HomeScreen(使用 'tabPress' 上的侦听器道具 => 导航回 HomeScreen) [堆栈1] 屏幕1 DetailScreen1 [堆栈2] 屏幕2 DetailScreen2 。 . . (其他 3 叠)

问题:

    嵌套/配置导航器以获得预期的最终结果的正确方法是什么?将 HomeScreen 作为父 Stack 和子 BottomTab 上的屏幕组件是否“安全”且正确?

    这似乎是一个繁重的解决方案(5 Stacks inside a Stack inside a Stack inside a Drawer,很快我将添加另一个堆栈用于授权屏幕),这会减慢应用程序的运行速度:是否有更有效的方式来组织导航器使用预先构建的导航器或构建即。 tabBar 的自定义组件,以便可能所有屏幕都在更少的堆栈中(一个?)或其他任何可以帮助我构建更轻量级解决方案的东西?

我在 expo.io 上发布了完整(简单)sample code 实现,下面是部分代码:

const DrawerNav = createDrawerNavigator();
const Drawer = ( navigation ) => 
  return (
    <DrawerNav.Navigator>
      <DrawerNav.Screen name="MainStack" component=MainStack />
      <DrawerNav.Screen name="OtherScreen" component=OtherScreen />
    </DrawerNav.Navigator>
  );
;

const MainStackNav = createStackNavigator();
const MainStack = ( navigation ) => 
  return (
    <MainStackNav.Navigator headerMode="none">
      <MainStackNav.Screen name="MainHome" component=HomeScreen />
      <MainStackNav.Screen name="MainBottomTab" component=BottomTab />
    </MainStackNav.Navigator>
  );
;

const BottomTabNav = createBottomTabNavigator();
const BottomTab = ( navigation ) => 
  return (
    <BottomTabNav.Navigator>
      <BottomTabNav.Screen name="Home" component=HomeScreen
        listeners=( navigation ) => (
        tabPress: (e) => 
          e.preventDefault();
          navigation.popToTop();
        ,
      )/>
      <BottomTabNav.Screen name="Stack1" component=Stack1 />
      <BottomTabNav.Screen name="Stack2" component=Stack2 />
      <BottomTabNav.Screen name="Stack3" component=Stack3 />
      <BottomTabNav.Screen name="Stack4" component=Stack4 />
      <BottomTabNav.Screen name="Stack5" component=Stack5 />
    </BottomTabNav.Navigator>
  );
;

【问题讨论】:

【参考方案1】:

即使这是可能的,您也应该避免在人机界面指南 (ios) 和两个平台的体验中的抽屉内使用 Tab-Navigator。 TabBars 的特殊之处在于它们在更改活动屏幕时保持状态。它们应该显示您的应用程序的主要模块。如果您有其他上下文或屏幕(如登录等),您可以添加模态屏幕等。

抽屉是指向标签栏的替代主导航,您可以在其中有许多用户想要直接访问的项目(通常超过 5 个)。

如果您想要一个包含其他项目的菜单,您可以将其放在一个(最后一个)选项卡上并称之为“更多...”

关于你的另一个问题,结构不是那么复杂,我使用更复杂的结构没有问题。如果你改变它,你只需要确保你不会迷失在结构中,所以尽量保持这段代码干净。并确保您的用户也不会在导航中迷路。

【讨论】:

关于性能改进我注意到:(1)TouchableOpacity 组件管理 onPress 比普通 Button 更快; (2) react-native-screens 的 NativeStacks 给了我另一个提升。您是否认为可以简化导航结构删除 MainStack 导航器:[Drawer] -&gt; [BottomTab] -&gt; ( HomeScreen , [Stack1] , ... ) 并使用 Animated 在屏幕安装时滑出/滑入 tabBar,避免使用 tabBarVisible 道具,否则这仍然让我面临屏幕风险ReactNavigation 记录的故障? 我不确定。 wix 人创建了自己的原生反应导航,因为他们对“标准”反应导航不满意。我的经验是,每次你尝试一些不标准的反应导航时,它都会在某处产生负面影响。组件创建的动画很困难,因为系统同时忙于两件事。

以上是关于使用堆栈中的外部屏幕正确嵌套底部选项卡的主要内容,如果未能解决你的问题,请参考以下文章

从嵌套屏幕导航到不同选项卡堆栈中的另一个嵌套屏幕(反应导航)

在 React Native 中始终显示底部选项卡导航器 React Navigation 5

颤动中的底部导航栏不会在点击选项卡时切换屏幕

Bootstrap 2.1 javascript嵌套选项卡:内部选项卡关闭外部选项卡

Jetpack Compose Navigation - 底部导航多个返回堆栈 - 查看模型范围问题

从反应原生底部选项卡导航器的标题导航