如何在 Tab 导航中添加 Header?

How to add a Header in Tab navigation?

我的导航系统使用经典的 stackNavigator,我在其中初始化了所有屏幕,并在页面底部使用其中 4 个屏幕初始化了 BottomTabNavigator。

我想在大多数屏幕的 header 中添加一个按钮。为此,我在每个 Stack.screen 的选项中添加了这些行,这有效:

headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),

另一方面,我无法在底部选项卡导航器屏幕的 header 中显示此按钮。我不明白为什么。我试过在 Tab.screen 和 Stack.screen 中做同样的事情,但没有结果。

我该怎么办?感谢任何愿意花时间向我解释问题并帮助我解决问题的人。

这是完整的代码:

const Stack = createStackNavigator();
let lang = retrieveAppLang();
const Tab = createBottomTabNavigator();
const screenOptionStyle = {
  headerStyle: {
    backgroundColor: "#F78400",    
  },  
  headerTintColor: "white",
  headerBackTitle: "Back",
  backgroundColor:'#f7f6f6'
};

function getHeaderTitle(route) {
  const routeName = getFocusedRouteNameFromRoute(route) ?? 'Orders'; // permet d'éviter que tous les écrans retournent 'Orders' dans le header comme précédemment
lang = retrieveAppLang();
  switch (routeName) {
    case 'Orders':
      return i18n.t('orders.title');
    case 'Dashboard':
      return i18n.t('dashboard.title');
    case 'Checkout':
      return i18n.t('checkout.title');
    case 'CashRegister':
      return i18n.t('cashregister.title');
    case 'Tools':
      return i18n.t('tools.title');
    case 'Settings':
      return i18n.t('settings.title');
    case 'Authentication': 
      return i18n.t("authentication.title") ;
    case 'Account': 
      return i18n.t("account.title");
    case 'Activities': 
      return i18n.t("activities.title"); 
    case 'Contact': 
      return i18n.t("contact.title"); 
    case 'Login': 
      return i18n.t("login.title");
    case 'Register': 
      return i18n.t("register.title");
    case 'Reset': 
      return i18n.t("reset.title");
    case 'Scan': 
      return i18n.t("scan.title");     
    case 'Current': 
      return i18n.t("current.title");
    case 'Completed': 
      return i18n.t("completed.title");
    case 'Products': 
      return i18n.t("products.title");
    case 'ProductDetails': 
      return i18n.t("fiche.title");
    case 'Information': 
      return i18n.t("information.title");
    case 'Photos': 
      return i18n.t("photos.title");
    case 'Stock': 
      return i18n.t("stock.title");
    case 'Terms': 
      return i18n.t("terms.title");
    case 'About': 
      return i18n.t("about.title");     
    case 'Tickets': 
      return i18n.t("tickets.title");
    case 'Dashboard': 
      return i18n.t("dashboard.title");    
    //case 'BottomTabNavigator': 
      //return i18n.t("welcome.title");
  }
}

export const MainStackNavigator = () => {
  return (
   <Stack.Navigator screenOptions={screenOptionStyle}>      
      <Stack.Screen 
        name = 'Orders' component = {BottomTabNavigator} 
        options={({route}) => ({
                    headerTitle: getHeaderTitle(route),})}/> 
      <Stack.Screen 
        name = 'Authentication' 
        component = {Authentication} 
        options={{title: i18n.t("authentication.title"), headerShown: false }}/>
      <Stack.Screen 
        name = 'Account' 
        component = {Account} 
        options={{ title: i18n.t("account.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                  style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen 
        name = 'Activities' 
        component = {Activities} 
        options={{ title: i18n.t("activities.title") }}/> 
      <Stack.Screen 
        name = 'Contact' 
        component = {Contact} 
        options={{ title: i18n.t("contact.title") }}/>
      <Stack.Screen 
        name = 'Checkout'
        component = {Checkout}
        options={{ title: i18n.t("checkout.title"),headerRight: () => (
            <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
              <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
            </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen
        name = 'CashRegister'
        component = {CashRegister}
        options={{ title: i18n.t("cashregister.title"), headerRight: () => (
            <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
              <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
            </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen 
        name = 'Login'
        component = {Login}
        options={{ title: i18n.t("login.title"), headerShown: false }}/>
      <Stack.Screen
        name = 'Register'
        component = {Register}
        options={{ title: i18n.t("register.title"), headerShown: false }}/>
      <Stack.Screen
        name = 'Reset'
        component = {Reset}
        options={{ title: i18n.t("reset.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen
        name = 'Tools'
        component = {Tools}
        options={{ title: i18n.t("tools.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
            ),
          }}/>
      <Stack.Screen
        name = 'Scan'
        component = {Scan}
        options={{ title: i18n.t("scan.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>      
      <Stack.Screen
        name = 'Current'
        component = {Current}
        options={{ title: i18n.t("current.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
            ),
          }}/>
      <Stack.Screen
        name = 'Completed'
        component = {Completed}
        options={{ title: i18n.t("completed.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen
        name = 'Products'
        component = {Products}
        options={{ title: i18n.t("products.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen
        name = 'ProductDetails'
        component = {ProductDetails}
        options={{ title: i18n.t("fiche.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen
        name = 'Information'
        component = {Information}
        options={{ title: i18n.t("information.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen
        name = 'Photos'
        component = {Photos}
        options={{ title: i18n.t("photos.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen
        name = 'Stock'
        component = {Stock}
        options={{ title: i18n.t("stock.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen
        name = 'Terms'
        component = {Terms}
        options={{ title: i18n.t("terms.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/> 
      <Stack.Screen
        name = 'About'
        component = {About}
        options={{ title: i18n.t("about.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>      
      <Stack.Screen
        name = 'Tickets'
        component = {Tickets}
        options={{ title: i18n.t("tickets.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen
        name = 'Dashboard'
        component = {Dashboard}
        options={{ title: i18n.t("dashboard.title")}}/>
      <Stack.Screen 
        name = 'Settings'
        component = {Settings}
        options={{ title: i18n.t("settings.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen
        name = 'Welcome'
        component = {Welcome}
        options={{ title: i18n.t("welcome.title"), headerRight: () => (
          <TouchableOpacity onPress={() => navigation.navigate('Activities')}>
            <Image source={require("./../assets/images/work.png")}
                    style={{width: 40, height: 40}} />                            
          </TouchableOpacity>
          ),
        }}/>
      <Stack.Screen name = 'BottomTabNavigator' component = {BottomTabNavigator} 
                                                options={({route}) => ({
                                                headerTitle: getHeaderTitle(route),})}/>
    </Stack.Navigator>
  );
}

export const BottomTabNavigator = (props) => {    
  if (lang.length == 2) {
    i18n.changeLanguage(lang);}
  return (
    <Tab.Navigator 
      tabBarOptions={{
        activeTintColor: 'black',
        lang: lang,
        labelStyle: {fontSize: 12, color: 'white'}, 
        style: {backgroundColor: '#F78400'}
      }}>
      <Tab.Screen
          name="Dashboard"
          component={Dashboard}
          options={{
            title: i18n.t('dashboard.title'),
            tabBarIcon: ({ focused, horizontal, tintColor }) => {
              return (
                <Image
                  source={require("../assets/images/dashboard.png")}
                  style={styles.icon}
                />
              );
            }
          }}
        />
      <Tab.Screen
        name='Orders'
        component={Orders}         
        options={{
          title: i18n.t('orders.title'),
          tabBarIcon: ({ focused, horizontal, tintColor }) => {
            return (
              <Image
                source={require("../assets/images/orders.png")}
                style={styles.icon}
              />
            );
          }
        }}
      />        
        <Tab.Screen
          name='Tools'
          component={Tools}
          options={{
            title: i18n.t('tools.title'),
            tabBarIcon: ({ focused, horizontal, tintColor }) => {
              return (
                <Image
                  source={require("../assets/images/tools.png")}
                  style={styles.icon}
                />
              );
            }
          }}
        />
        <Tab.Screen
          name='Settings'          
          component={Settings}
          options={{
            title: i18n.t('settings.title'),
            tabBarIcon: ({ focused, horizontal, tintColor }) => {
              return (
                <Image
                  source={require("../assets/images/settings.png")}
                  style={styles.icon}
                />
              );
            }
          }}
        />
    </Tab.Navigator>
  );
};

您需要添加一个堆栈导航器作为每个底部选项卡屏幕的屏幕。然后你可以自定义headers.