Material Top Tabs 导航器
屏幕顶部的 Material Design 主题标签栏,允许您通过点击标签或水平滑动在不同路由之间切换。默认情况下,过渡会进行动画处理。每个路由的屏幕组件都会立即挂载。
此导航器包装了 react-native-tab-view
。如果您想在不集成 React Navigation 的情况下使用标签页视图,请直接使用该库。
安装
要使用此导航器,请确保您已安装 @react-navigation/native
及其依赖项(请遵循本指南),然后安装 @react-navigation/material-top-tabs
- npm
- Yarn
- pnpm
npm install @react-navigation/material-top-tabs
yarn add @react-navigation/material-top-tabs
pnpm add @react-navigation/material-top-tabs
然后,您需要安装 react-native-pager-view
,这是导航器所必需的。
如果您有一个 Expo 管理的项目,请在您的项目目录中运行
npx expo install react-native-pager-view
如果您有一个裸 React Native 项目,请在您的项目目录中运行
- npm
- Yarn
- pnpm
npm install react-native-pager-view
yarn add react-native-pager-view
pnpm add 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,
},
});
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
const Tab = createMaterialTopTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
);
}
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
通用标题,可以用作 headerTitle
和 tabBarLabel
的后备。
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
- If the screen for the tab renders a scroll view, you can use
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 }],
}}
/>
);
}