reactjsreact-nativereact-navigationreact-navigation-v5react-navigation-top-tabs

How to render material top tab navigator inside a custom header component


I would like to render material top tab navigator created with createMaterialTopTabNavigator() from react-navigation inside a custom header component. Indeed, my header is a gradient, so I need to have tabs into the header like this:

enter image description here

So I set a marginTop negative on the tab bar to have it on the header:

// AppNavigator.ts
function MyTabStack() {
  const TabStack = createMaterialTopTabNavigator();

  return (
    <TabStack.Navigator
      initialRouteName="MyTabScreen1"
      lazy={true}
      style={{
        marginTop: -40 - 14,
        zIndex: 1,
      }}
      tabBarOptions={{
        style: {
          backgroundColor: 'transparent',
          height: 50,
        },
      }}>
      <TabStack.Screen
        name="MyTabScreen1"
        component={MyTabScreen1}
        options={{ title: 'Tab 1' }}
      />
      <TabStack.Screen
        name="MyTabScreen2"
        component={MyTabScreen2}
        options={{ title: 'Tab 2' }}
      />
    </TabStack.Navigator>
  );
}

function App() {
  return (
    <SafeAreaProvider>
      <NavigationContainer
        <Stack.Navigator headerMode="screen" initialRouteName="MyScreen">
        <StackFidelity.Screen
           name="MyScreen"
           options={() => ({
             header: ({ options }) => <MyGradientHeader {...options} />,
          })}
          component={MyTabStack}
       />
       </Stack.Navigator>
    </NavigationContainer>
  );
}

It works well on Android, but not on iOS because tab bar is behind the header (I don't know why). I can reporduce on expo (web version): Expo link Do you have a solution for that?


Solution

  • Finally, I remove header from my top Navigator

    function App() {
      return (
        <SafeAreaProvider>
          <NavigationContainer
            <Stack.Navigator initialRouteName="MyScreen">
                <StackFidelity.Screen
                    name="MyScreen"
                    options={{ headerShown: false }}
                    component={MyTabStack}
           />
           </Stack.Navigator>
        </NavigationContainer>
      );
    }
    

    And create a custom tab component (CustomTabHeader) with gradiant and tab which I used as header

    function MyTabStack() {
        const Tab = createMaterialTopTabNavigator();
    
      return (
        <Tab.Navigator
          initialRouteName="LittleCardsScene"
          tabBarPosition="top"
          tabBar={(props) => <CustomTabHeader {...props} />}
    .....