如何在 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.
我的导航系统使用经典的 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.