跳至主要内容
版本: 6.x

底部标签导航器

一个简单的底部标签栏,允许您在不同的路由之间切换。路由是延迟初始化的 - 它们的屏幕组件只有在首次聚焦时才会被挂载。

安装

要使用此导航器,请确保您已安装 @react-navigation/native 及其依赖项(请遵循本指南),然后安装 @react-navigation/bottom-tabs

npm install @react-navigation/bottom-tabs

API 定义

要使用此标签导航器,请从 @react-navigation/bottom-tabs 中导入它

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const Tab = createBottomTabNavigator();

function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
);
}
注意

有关完整的使用指南,请访问 标签导航

属性

Tab.Navigator 组件接受以下属性

id

导航器的可选唯一 ID。这可以与 navigation.getParent 一起使用,以在子导航器中引用此导航器。

initialRouteName

在首次加载导航器时要渲染的路由的名称。

screenOptions

用于导航器中屏幕的默认选项。

backBehavior

这控制在导航器中调用 goBack 时会发生什么。这包括按下设备的返回按钮或 Android 上的返回手势。

它支持以下值

  • firstRoute - 返回到导航器中定义的第一个屏幕(默认)
  • initialRoute - 返回到 initialRouteName 属性中传递的初始屏幕,如果未传递,则默认为第一个屏幕
  • order - 返回到聚焦屏幕之前定义的屏幕
  • history - 返回到导航器中最后访问的屏幕;如果多次访问同一个屏幕,则历史记录中的旧条目将被删除
  • none - 不处理返回按钮

detachInactiveScreens

布尔值,用于指示是否应将非活动屏幕从视图层次结构中分离以节省内存。这允许与 react-native-screens 集成。默认为 true

sceneContainerStyle

包裹屏幕内容的组件的样式对象。

tabBar

返回一个 React 元素的函数,该元素将显示为选项卡栏。

示例

import { View, Text, TouchableOpacity } from 'react-native';

function MyTabBar({ state, descriptors, navigation }) {
return (
<View style={{ flexDirection: 'row' }}>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;

const isFocused = state.index === index;

const onPress = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,
});

if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name, route.params);
}
};

const onLongPress = () => {
navigation.emit({
type: 'tabLongPress',
target: route.key,
});
};

return (
<TouchableOpacity
accessibilityRole="button"
accessibilityState={isFocused ? { selected: true } : {}}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarTestID}
onPress={onPress}
onLongPress={onLongPress}
style={{ flex: 1 }}
>
<Text style={{ color: isFocused ? '#673ab7' : '#222' }}>
{label}
</Text>
</TouchableOpacity>
);
})}
</View>
);
}

// ...

<Tab.Navigator tabBar={props => <MyTabBar {...props} />}>
{...}
</Tab.Navigator>

此示例将渲染一个带有标签的基本选项卡栏。

请注意,您**不能**在tabBar中使用useNavigation钩子,因为useNavigation仅在屏幕内可用。您可以获得tabBarnavigation道具,您可以使用它来代替。

function MyTabBar({ navigation }) {
return (
<Button
title="Go somewhere"
onPress={() => {
// Navigate using the `navigation` prop that you received
navigation.navigate('SomeScreen');
}}
/>
);
}

选项

以下选项可用于配置导航器中的屏幕。这些可以在Tab.navigatorscreenOptions道具或Tab.Screenoptions道具下指定。

title

通用标题,可用作headerTitletabBarLabel的回退。

tabBarLabel

在选项卡栏中显示的选项卡的标题字符串,或者是一个函数,该函数在给定{ focused: boolean, color: string }时返回一个 React.Node,以在选项卡栏中显示。如果未定义,则使用场景title。要隐藏,请参见tabBarShowLabel

tabBarShowLabel

选项卡标签是否应可见。默认为true

tabBarLabelPosition

标签是否显示在图标下方或图标旁边。

  • below-icon:标签显示在图标下方(通常用于 iPhone)
  • beside-icon 标签显示在图标旁边(通常用于 iPad)

默认情况下,位置会根据设备宽度自动选择。

tabBarLabelStyle

标签的样式对象。

tabBarIcon

接收{ focused: boolean, color: string, size: number }并返回一个 React.Node 的函数,用于在标签栏中显示。

tabBarIconStyle

标签图标的样式对象。

tabBarBadge

在标签图标上显示的徽章文本。接受stringnumber

tabBarBadgeStyle

标签图标上徽章的样式。您可以在此处指定背景颜色或文本颜色。

tabBarAccessibilityLabel

标签按钮的可访问性标签。当用户点击标签时,屏幕阅读器会读取此标签。如果您没有标签的标签,建议设置此标签。

tabBarTestID

在测试中定位此标签按钮的 ID。

tabBarButton

返回一个 React 元素作为标签栏按钮渲染的函数。它包装了图标和标签。默认情况下渲染Pressable

您可以在此处指定自定义实现

tabBarButton: (props) => <TouchableOpacity {...props} />;

tabBarActiveTintColor

活动标签中图标和标签的颜色。

tabBarInactiveTintColor

非活动标签中图标和标签的颜色。

tabBarActiveBackgroundColor

活动标签的背景颜色。

tabBarInactiveBackgroundColor

非活动标签的背景颜色。

tabBarHideOnKeyboard

键盘打开时是否隐藏标签栏。默认值为 false

tabBarItemStyle

标签项容器的样式对象。

tabBarStyle

标签栏的样式对象。您可以在此处配置背景颜色等样式。

要将您的屏幕显示在标签栏下方,您可以将 position 样式设置为 absolute

<Tab.Navigator
screenOptions={{
tabBarStyle: { position: 'absolute' },
}}
>

如果您有一个绝对定位的标签栏,您可能还需要为您的内容添加底部边距。React Navigation 不会自动执行此操作。

要获取底部标签栏的高度,您可以使用 BottomTabBarHeightContextReact 的 Context APIuseBottomTabBarHeight

import { BottomTabBarHeightContext } from '@react-navigation/bottom-tabs';

// ...

<BottomTabBarHeightContext.Consumer>
{tabBarHeight => (
/* render something */
)}
</BottomTabBarHeightContext.Consumer>

import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';

// ...

const tabBarHeight = useBottomTabBarHeight();

tabBarBackground

返回一个 React 元素的函数,用作标签栏的背景。您可以渲染图像、渐变、模糊视图等。

import { BlurView } from 'expo-blur';

// ...

<Tab.Navigator
screenOptions={{
tabBarStyle: { position: 'absolute' },
tabBarBackground: () => (
<BlurView tint="light" intensity={100} style={StyleSheet.absoluteFill} />
),
}}
>

使用 BlurView 时,请确保在 tabBarStyle 中也设置 position: 'absolute'。您还需要使用 useBottomTabBarHeight() 为您的内容添加底部填充。

lazy

这些屏幕是否应该在第一次访问时渲染。默认值为 true。如果您想在初始渲染时渲染屏幕,请将其设置为 false

unmountOnBlur

当导航离开此屏幕时,是否应该卸载此屏幕。卸载屏幕会重置屏幕中的任何本地状态以及屏幕中嵌套导航器的状态。默认值为 false

通常,我们不建议启用此道具,因为用户不希望在切换标签时丢失他们的导航历史记录。如果您启用了此道具,请考虑这是否会真正为用户提供更好的体验。

freezeOnBlur

布尔值,指示是否阻止非活动屏幕重新渲染。默认值为 false。当从 react-native-screens 包中运行 enableFreeze() 时,默认值为 true

需要 react-native-screens 版本 >=3.16.0。

仅在 iOS 和 Android 上支持。

您可以在 此处 找到与标题相关的选项列表。这些 选项 可以指定在 Tab.navigatorscreenOptions 属性或 Tab.Screenoptions 属性下。您不必直接使用 @react-navigation/elements 就可以使用这些选项,它们只是在该页面中进行了记录。

除了这些选项之外,底部选项卡还支持以下选项

要使用的自定义标题,以代替默认标题。

这接受一个函数,该函数返回一个 React 元素,作为标题显示。该函数接收一个包含以下属性的对象作为参数

  • navigation - 当前屏幕的导航对象。
  • route - 当前屏幕的路由对象。
  • options - 当前屏幕的选项
  • layout - 屏幕的尺寸,包含 heightwidth 属性。

示例

import { getHeaderTitle } from '@react-navigation/elements';

// ..

header: ({ navigation, route, options }) => {
const title = getHeaderTitle(options, route.name);

return <MyHeader title={title} style={options.headerStyle} />;
};

要为导航器中的所有屏幕设置自定义标题,您可以在导航器的 screenOptions 属性中指定此选项。

headerStyle 中指定 height

如果您的自定义标题的高度与默认标题的高度不同,那么您可能会注意到由于测量是异步的而导致的故障。明确指定高度将避免此类故障。

示例

headerStyle: {
height: 80, // Specify the height of your custom header
};

请注意,此样式默认情况下不会应用于标题,因为您控制自定义标题的样式。如果您还想将此样式应用于标题,请使用来自道具的 options.headerStyle

headerShown

是否显示或隐藏屏幕的标题。默认情况下显示标题。将其设置为 false 会隐藏标题。

事件

导航器可以在某些操作时发出事件。支持的事件有

tabPress

当用户按下标签栏中当前屏幕的标签按钮时,会触发此事件。默认情况下,按下标签会执行以下操作

  • 如果标签未获得焦点,按下标签会使该标签获得焦点
  • 如果标签已获得焦点
    • 如果标签的屏幕渲染了滚动视图,可以使用useScrollToTop将其滚动到顶部
    • 如果标签的屏幕渲染了堆栈导航器,则会在堆栈上执行popToTop操作

要阻止默认行为,可以调用event.preventDefault

React.useEffect(() => {
const unsubscribe = navigation.addListener('tabPress', (e) => {
// Prevent default behavior
e.preventDefault();

// Do something manually
// ...
});

return unsubscribe;
}, [navigation]);

如果您有自定义标签栏,请确保发出此事件。

tabLongPress

当用户长时间按下标签栏中当前屏幕的标签按钮时,会触发此事件。如果您有自定义标签栏,请确保发出此事件。

示例

React.useEffect(() => {
const unsubscribe = navigation.addListener('tabLongPress', (e) => {
// Do something
});

return unsubscribe;
}, [navigation]);

辅助函数

标签导航器将以下方法添加到导航属性中

jumpTo

导航到标签导航器中的现有屏幕。该方法接受以下参数

  • name - string - 要跳转到的路由的名称。
  • params - object - 要用于目标路由的屏幕参数。
navigation.jumpTo('Profile', { owner: 'Michaś' });

示例

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';

const Tab = createBottomTabNavigator();

function MyTabs() {
return (
<Tab.Navigator
initialRouteName="Feed"
screenOptions={{
tabBarActiveTintColor: '#e91e63',
}}
>
<Tab.Screen
name="Feed"
component={Feed}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Notifications"
component={Notifications}
options={{
tabBarLabel: 'Updates',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="bell" color={color} size={size} />
),
tabBarBadge: 3,
}}
/>
<Tab.Screen
name="Profile"
component={Profile}
options={{
tabBarLabel: 'Profile',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="account" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
);
}