【问题标题】:how to display headers in react navigation with TabNavigation如何使用 TabNavigation 在反应导航中显示标题
【发布时间】:2017-02-21 00:50:10
【问题描述】:

我注意到 StackNavigation 中的视图显示标题标题,但如果我在 TabNavigation 中设置相同的屏幕,它不会显示标题。如果我将 StackNavigation 包裹在每个选项卡周围,或者将 TabNavigation 嵌套在 StackNavigation 中,它只会显示标题。

为什么 TabNavigation 中的屏幕不显示标题 - 这是预期的行为吗?如果是这样,是在每个选项卡中都有一个 StackNavigation,还是在 TabNavigation 周围有一个大的 StackNavigation?

//标签导航在每个屏幕中不显示标题

const TabsNavigator = TabNavigator({
  Home: {
    screen:HomeScreen,
  },
  Profile: {
    screen: ProfileScreen,
  },
}, {
  tabBarOptions: {
    activeTintColor: '#e91e63',
  },
  navigationOptions: {
    header: {
      visible: true,
    },
  },
});

当我将它包装在 StackNavigator 中时会显示标题

default StackNavigator({
  Home: { screen: TabsNavigator },
});

还是这样做更好

 export TabsNavigator = TabNavigator({
      Home: {
        screen:StackNavigator({
          Home: { screen: HomeScreen },
        }),
      },
      Profile: {
        screen: StackNavigator({Profile: {screen: ProfileScreen}}),
      },
    }, {
      tabBarOptions: {
        activeTintColor: '#e91e63',
      },
      navigationOptions: {
        header: {
          visible: true,
        },
      },
    });

【问题讨论】:

  • 这是预期的行为。如果你想有一个标题,你确实必须在每个选项卡中放置一个 StackNavigator,或者你必须自己创建一个标题。
  • 我在这里找到了解决方案 - stackoverflow.com/questions/53915174/… 使用该方法不需要使用 StackNavigator 进行包装

标签: react-native react-navigation


【解决方案1】:

即使这是一个相当老的问题,几天前我自己也有这个问题,所以我会加两分钱,希望这对未来的其他人也有用。

React Navigation 是一款出色的产品,具有大量的自定义功能,但有时也会令人困惑,这也适用于文档的某些部分。 navigationOptions 在当前版本状态下,对所有屏幕都是通用的,但“可用导航选项列表取决于添加屏幕的导航器”。 https://reactnavigation.org/docs/tab-navigator.html#navigationoptions-used-by-tabnavigator 因此 header 选项不起作用,因为它不适用于 TabNavigator 本身。

关于哪种方法最好的问题取决于您希望通过应用本身的导航来完成什么。如果将TabNavigator 放在StackNavigator 中,则标题组件对于TabNavigator 中的所有选项卡都是通用的,这意味着选项卡转换将生效,但标题不会从其顶部位置移动。另一方面,如果您选择在每个选项卡内嵌套StackNavigator,则标题将在每个选项卡内呈现,这意味着标题将沿着选项卡过渡动画移动。

我快速创建了一个demo 让你看看有什么不同,如果你想玩的话,code 也可以。

【讨论】:

  • 感谢您的回答!它看起来很笨拙,但添加另一个 StackNavigator,但它就像一个魅力。
  • 谢谢!我已经实现了这个,并且工作得很好,但是当我想调用一个新屏幕(使用 StackNavigator)时,我得到了这个:TypeError undefined is not an object (evaluating 'this.props.navigation.navigate')我有这个结构:<View><Header /><NestedTabNavigator /></View>我正在使用 react-native-元素 Header 组件,并将rightComponent 设置为组件类(在同一个文件中,App.js),并在此组件中,在渲染方法中我执行const { navigate } = this.props.navigation;,然后在按钮中onPress={ () => navigate('ContactoScreen') }
  • 我喜欢你的解释?
  • 感谢演示,但是当我打开链接时显示“此项目使用 Expo SDK v22.0.0。如果要打开此项目,作者需要更新项目的 SDK 版本。 "
【解决方案2】:

我知道这个问题已经有了答案,但我想展示一下我是如何使用React Navigation > 5.x.x 为自己完成这项工作的。

Juan 的回答描述了设置它的最佳方式,但也展示了它是如何完成的,以便人们能够理解导航的样子,这对我们视觉学习者也有一点帮助。这在当时对我来说有点难以理解,但希望它对未来的其他人有所帮助。

我发现最好的方法是分解应用程序路由的层次结构。对我来说,我的看起来像这样。

               LoginNavigation                      HomeNavigation   
                     |                                    |
      LoginScreen        RegisterScreen        HomeStack      ProfileStack
                                                   |               |
                                              HomesScreen     ProfileScreen

我的LoginNavigation 堆栈包含两个屏幕,登录屏幕和注册屏幕。在我的应用程序中,我不需要在此处设置选项卡导航,因此将这些屏幕包裹在 StackNavigator 中是合适的。另一方面,我有我的 HomeNavigation 堆栈,其中包含一个主屏幕和一个配置文件屏幕。唯一的问题是我的屏幕被包裹在 TabNavigator 中,它不会产生标题。

要解决这个问题,我们实际上需要将两个屏幕(HomeScreen 和 ProfileScreen)封装在 StackNavigators 中,然后使用 TabNavigator 封装所有内容。在意识到这一点之后,这样做实际上更有意义。为什么?好吧,假设在我的主屏幕上我有一些帖子,我希望用户能够看到帖子以及它附带的所有 cmets。好吧,我不会为此设置另一个选项卡,因为那太愚蠢了。相反,我们会将其添加到 HomeStack 导航中,而不是像这样。

                       HomeNavigation   
                             |
            HomeStack                 ProfileStack
                 |                         |
     HomesScreen    PostScreen       ProfileScreen

当查看诸如 ProfileStack 之类的东西时,这种结构现在似乎很明显,该堆栈可能有多个分支,例如 Settings、Followers、Pictures... 希望展示结构能帮助别人理解这一点,也对我有所帮助。

下面是我的AppStackNavigator 文件,可以查看代码中的结构。

import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import Login from '../screens/Login';
import Register from '../screens/Register';
import FirstProfileImage from '../screens/FirstProfileImage';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Home from '../screens/Home';
import Profile from './../screens/Profile';

const LoginStack = createStackNavigator();
const HomeTabs = createBottomTabNavigator();
const HomeStack = createStackNavigator();
const ProfileStack = createStackNavigator();
const AppStack = createStackNavigator();

const LoginStackNavigator = () => (
  <LoginStack.Navigator screenOptions={{headerStyle: {elevation: 0},cardStyle: {backgroundColor: '#ffffff'}}}>
    <LoginStack.Screen name="Login" component={Login}/>
    <LoginStack.Screen name="Sign Up" component={Register}/>
    <LoginStack.Screen name="Profile Image" component={FirstProfileImage}/>
  </LoginStack.Navigator>
)

const HomeStackNavigator = () => (
  <HomeStack.Navigator>
    <HomeStack.Screen name="Home" component={Home} />
  </HomeStack.Navigator>
)

const ProfileStackNavigator = () => (
  <ProfileStack.Navigator>
    <ProfileStack.Screen name="Profile" component={Profile} />
  </ProfileStack.Navigator>
)

const HomeTabNavigator = () => (
    <HomeTabs.Navigator>
      <HomeTabs.Screen name="HomeStack" component={HomeStackNavigator} />
      <HomeTabs.Screen name="ProfileStack" component={ProfileStackNavigator} />
    </HomeTabs.Navigator> 
)

const AppStackNavigator = () => (
    <AppStack.Navigator initialRouteName={'HomeScreen'} screenOptions={{headerStyle: {elevation: 0},cardStyle: {backgroundColor: '#ffffff'}}} headerMode='none'>
      <AppStack.Screen name="LoginScreen" component={LoginStackNavigator}/>
      <AppStack.Screen name="HomeScreen" component={HomeTabNavigator}/>
    </AppStack.Navigator>  
)

export default AppStackNavigator;

我同意这有点矫枉过正,我们可以消除必须跟踪每个导航器的问题,但在他们为此添加功能之前,这是目前可行的方法。希望这个解释有点帮助。感谢您参加我的 TED 演讲。

【讨论】:

    【解决方案3】:

    根据React-Navigation TabNavigator Docs 没有标题导航选项。因此,当您编写以下代码时,您实际上是在设置一个不存在的值,因此您所做的不会影响任何事情。

    navigationOptions: {
      header: { visible: true },
    }
    

    遗憾的是,在这种情况下您需要 StackNavigator。

    【讨论】:

    • 我不完全确定这是否是新的,但在navigationOptions 中有一个header 属性,在@987654326 内@ 文档,但他可能错过的是 navigationOptions 对象,它不是具有所有属性的全局对象,它们取决于导航器本身 reactnavigation.org/docs/navigators/stack#header
    • 感谢您告诉我。在我写这个答案时,我不记得它存在,但它可能在此期间发生了变化。
    • @JuanCarlosAlpizarChinchilla 感谢源代码!又好又甜!
    • @shimatai yw!总是乐于提供帮助:)
    【解决方案4】:

    我使用的一般结构是这样的,创建一个选项卡导航器,然后为每个选项卡呈现堆栈。在此示例中,我不想在 LiveMap 上显示标题,但在其他两个选项卡上需要。任何有意义的命名都取决于您。然后在每个堆栈中渲染有意义的屏幕。

    const Tab = createBottomTabNavigator();
    const TrainStack = createStackNavigator();
    const MapStack = createStackNavigator();
    const BusStack = createStackNavigator();
    

    然后每个堆栈都会为该子集呈现我想要的任何屏幕

    const MapNavigator = () => {
      return (
        <MapStack.Navigator
          initialRouteName="LiveMap"
          screenOptions={{headerShown: false}}>
          <MapStack.Screen name="Live Map" component={LiveMap} />
          <MapStack.Screen name="Show Routes" component={AllRoutes} />
          <MapStack.Screen name="Select Routes" component={SelectRoutes} />
        </MapStack.Navigator>
      );
    };
    

    标签导航器将为每个标签呈现我的堆栈。

    const MainNavigator = () => (
      <Tab.Navigator
        tabBarOptions={{
          activeTintColor: 'orange',
          keyboardHidesTabBar: true,
        }}
        initialRouteName="Live Map">
        <Tab.Screen
          name="Buses"
          component={BusNavigator}
          options={{
            tabBarLabel: 'Buses',
            tabBarIcon: ({color, size}) => (
              <BusIcon height={30} width={30} color={color} />
            ),
          }}
        />
        <Tab.Screen
          name="Live Map"
          component={MapNavigator}
          options={{
            tabBarLabel: 'Map',
            tabBarIcon: ({color}) => (
              <View
                height={100}
                width={100}
                style={{
                  display: 'flex',
                  alignItems: 'center',
                  backgroundColor: '#fff',
                  paddingTop: 8,
                  borderRadius: 70,
                }}>
                <MapIcon height={50} width={50} color="orange" />
              </View>
            ),
          }}
        />
        <Tab.Screen
          name="Trains"
          component={TrainNavigator}
          options={{
            tabBarLabel: 'Trains',
            tabBarIcon: ({color, size}) => (
              <TrainIcon height={30} width={30} color={color} />
            ),
          }}
        />
      </Tab.Navigator>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      • 2019-10-28
      • 1970-01-01
      • 2018-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多