底部标签导航器
一个简单的底部标签栏,允许您在不同的路由之间切换。路由是延迟初始化的 - 它们的屏幕组件只有在首次聚焦时才会被挂载。
安装
要使用此导航器,请确保您已安装 @react-navigation/native
及其依赖项(请遵循本指南),然后安装 @react-navigation/bottom-tabs
- npm
- Yarn
- pnpm
npm install @react-navigation/bottom-tabs
yarn add @react-navigation/bottom-tabs
pnpm add @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
仅在屏幕内可用。您可以获得tabBar
的navigation
道具,您可以使用它来代替。
function MyTabBar({ navigation }) {
return (
<Button
title="Go somewhere"
onPress={() => {
// Navigate using the `navigation` prop that you received
navigation.navigate('SomeScreen');
}}
/>
);
}
选项
以下选项可用于配置导航器中的屏幕。这些可以在Tab.navigator
的screenOptions
道具或Tab.Screen
的options
道具下指定。
title
通用标题,可用作headerTitle
和tabBarLabel
的回退。
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
在标签图标上显示的徽章文本。接受string
或number
。
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 不会自动执行此操作。
要获取底部标签栏的高度,您可以使用 BottomTabBarHeightContext
与 React 的 Context API 或 useBottomTabBarHeight
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.navigator
的 screenOptions
属性或 Tab.Screen
的 options
属性下。您不必直接使用 @react-navigation/elements
就可以使用这些选项,它们只是在该页面中进行了记录。
除了这些选项之外,底部选项卡还支持以下选项
header
要使用的自定义标题,以代替默认标题。
这接受一个函数,该函数返回一个 React 元素,作为标题显示。该函数接收一个包含以下属性的对象作为参数
navigation
- 当前屏幕的导航对象。route
- 当前屏幕的路由对象。options
- 当前屏幕的选项layout
- 屏幕的尺寸,包含height
和width
属性。
示例
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>
);
}