跳到主要内容
版本:7.x

Material Top Tabs 导航器

屏幕顶部的 Material Design 主题标签栏,允许您通过点击标签或水平滑动在不同路由之间切换。默认情况下,过渡会进行动画处理。每个路由的屏幕组件都会立即挂载。

此导航器包装了 react-native-tab-view。如果您想在不集成 React Navigation 的情况下使用标签页视图,请直接使用该库。

安装

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

npm install @react-navigation/material-top-tabs

然后,您需要安装 react-native-pager-view,这是导航器所必需的。

如果您有一个 Expo 管理的项目,请在您的项目目录中运行

npx expo install react-native-pager-view

如果您有一个裸 React Native 项目,请在您的项目目录中运行

npm install react-native-pager-view

如果您在 Mac 上为 iOS 开发,您还需要安装 pods(通过 Cocoapods)以完成链接。

npx pod-install ios

用法

要使用此导航器,请从 @react-navigation/material-top-tabs 导入它

import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';

const MyTabs = createMaterialTopTabNavigator({
screens: {
Home: HomeScreen,
Profile: ProfileScreen,
},
});
Snack 上尝试

API 定义

Props

除了所有导航器共享的通用 props 之外,material top tabs 导航器组件还接受以下附加 props

backBehavior

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

它支持以下值

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

tabBarPosition

标签页视图中标签栏的位置。可能的值为 'top''bottom'。默认为 'top'

keyboardDismissMode

字符串,指示键盘是否会响应拖动手势而关闭。可能的值为

  • 'auto'(默认):当索引更改时,键盘将关闭。
  • 'on-drag':当拖动开始时,键盘将关闭。
  • 'none':拖动不会关闭键盘。

initialLayout

包含屏幕初始高度和宽度的对象。传递此对象将提高初始渲染性能。对于大多数应用程序,这是一个很好的默认值

{
width: Dimensions.get('window').width;
}

style

应用于标签页视图容器的样式。

tabBar

返回一个 React 元素以显示为标签栏的函数。

示例

import { Animated, View, TouchableOpacity, Platform } from 'react-native';
import { useLinkBuilder, useTheme } from '@react-navigation/native';

function MyTabBar({ state, descriptors, navigation, position }) {
const { colors } = useTheme();
const { buildHref } = useLinkBuilder();

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,
});
};

const inputRange = state.routes.map((_, i) => i);
const opacity = position.interpolate({
inputRange,
outputRange: inputRange.map((i) => (i === index ? 1 : 0)),
});

return (
<TouchableOpacity
href={buildHref(route.name, route.params)}
accessibilityRole={Platform.OS === 'web' ? 'link' : 'button'}
accessibilityState={isFocused ? { selected: true } : {}}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarButtonTestID}
onPress={onPress}
onLongPress={onLongPress}
style={{ flex: 1 }}
>
<Animated.Text style={{ opacity, color: colors.text }}>
{label}
</Animated.Text>
</TouchableOpacity>
);
})}
</View>
);
}

// ...

<Tab.Navigator tabBar={(props) => <MyTabBar {...props} />}>
{/* ... */}
</Tab.Navigator>;

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

请注意,您不能tabBar 内部使用 useNavigation hook,因为 useNavigation 仅在屏幕内部可用。您可以为您的 tabBar 获取一个 navigation prop,您可以改为使用它

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

选项

以下 选项 可用于配置导航器中的屏幕

示例

<Tab.Navigator
screenOptions={{
tabBarLabelStyle: { fontSize: 12 },
tabBarItemStyle: { width: 100 },
tabBarStyle: { backgroundColor: 'powderblue' },
}}
>
{/* ... */}
</Tab.Navigator>

title

通用标题,可以用作 headerTitletabBarLabel 的后备。

tabBarLabel

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

tabBarAccessibilityLabel

标签按钮的辅助功能标签。当用户点击标签时,屏幕阅读器会读取此标签。如果您没有标签,建议设置此项。

tabBarAllowFontScaling

标签字体是否应缩放以符合“文本大小”辅助功能设置。

tabBarShowLabel

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

tabBarIcon

一个函数,给定 { focused: boolean, color: string } 返回一个 React.Node,以在标签栏中显示。

tabBarShowIcon

标签图标是否应可见。默认为 false

tabBarBadge

返回一个 React 元素以用作标签徽章的函数。

tabBarIndicator

返回一个 React 元素作为标签栏指示器的函数。

tabBarIndicatorStyle

标签栏指示器的样式对象。

tabBarIndicatorContainerStyle

包含标签栏指示器的视图的样式对象。

tabBarButtonTestID

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

tabBarActiveTintColor

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

tabBarInactiveTintColor

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

tabBarPressColor

Material 波纹效果的颜色(仅限 Android >= 5.0)。

tabBarPressOpacity

按下标签的不透明度(仅限 iOS 和 Android < 5.0)。

tabBarBounces

布尔值,指示标签栏在过度滚动时是否反弹。

tabBarScrollEnabled

布尔值,指示是否使标签栏可滚动。

如果将其设置为 true,您还应该在 tabBarItemStyle 中指定宽度,以提高初始渲染的性能。

tabBarLabelStyle

标签标签的样式对象。

tabBarItemStyle

各个标签项的样式对象。

tabBarContentContainerStyle

包含标签项的视图的样式对象。

tabBarStyle

标签栏的样式对象。

swipeEnabled

布尔值,指示是否启用滑动

lazy

Whether this screen should be lazily rendered. When this is set to true, the screen will be rendered as it comes into the viewport. By default all screens are rendered to provide a smoother swipe experience. But you might want to defer the rendering of screens out of the viewport until the user sees them. To enable lazy rendering for this screen, set lazy to true.

When you enable lazy, the lazy loaded screens will usually take some time to render when they come into the viewport. You can use the lazyPlaceholder prop to customize what the user sees during this short period.

lazyPreloadDistance

When lazy is enabled, you can specify how many adjacent screens should be preloaded in advance with this prop. This value defaults to 0 which means lazy pages are loaded as they come into the viewport.

lazyPlaceholder

Function that returns a React element to render if this screen hasn't been rendered yet. The lazy option also needs to be enabled for this to work.

This view is usually only shown for a split second. Keep it lightweight.

By default, this renders null.

sceneStyle

Style to apply to the view wrapping each screen. You can pass this to override some default styles such as overflow clipping.

Events

The navigator can emit events on certain actions. Supported events are

tabPress

This event is fired when the user presses the tab button for the current screen in the tab bar. By default a tab press does several things

  • If the tab is not focused, tab press will focus that tab
  • If the tab is already focused
    • If the screen for the tab renders a scroll view, you can use useScrollToTop to scroll it to top
    • If the screen for the tab renders a stack navigator, a popToTop action is performed on the stack

To prevent the default behavior, you can call event.preventDefault

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

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

return unsubscribe;
}, [navigation]);

tabLongPress

This event is fired when the user presses the tab button for the current screen in the tab bar for an extended period.

示例

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

return unsubscribe;
}, [navigation]);

Helpers

The tab navigator adds the following methods to the navigation object

jumpTo

Navigates to an existing screen in the tab navigator. The method accepts following arguments

  • name - string - Name of the route to jump to.
  • params - object - Screen params to pass to the destination route.
navigation.jumpTo('Profile', { name: 'Michaś' });

Hooks

The material top tab navigator exports the following hooks

useTabAnimation

This hook returns an object containing an animated value that represents the current position of the tabs. This can be used to animate elements based on the swipe position of the tabs, such as the tab indicator

import { Animated } from 'react-native';
import { useTabAnimation } from '@react-navigation/material-top-tabs';

function MyView() {
const { position } = useTabAnimation();

return (
<Animated.View
style={{
width: '50%',
height: 2,
backgroundColor: 'tomato',
transform: [{ translateX: position }],
}}
/>
);
}