PagerView
与 react-native-pager-view 兼容的水平分页视图。
For the complete documentation index, see llms.txt. Use this file to discover all available pages.
一个与 react-native-pager-view API 兼容的 PagerView 组件。它封装了平台特定的 @expo/ui 基元:Android 上的 Jetpack Compose HorizontalPager,以及 iOS 上的分页 SwiftUI ScrollView。每个子项都会成为单独的一页,并拉伸以填满 pager。
如果你需要对平台特定的分页行为或修饰器进行更底层的控制,请直接使用原生基元。在 iOS 上,使用 TabView 并设置 page 样式,也会渲染一个水平 pager,并且当你想要 SwiftUI 内置的分页指示器时,它可能更适合。
安装
- npx expo install @expo/uiIf you are installing this in an existing React Native app, make sure to install expo in your project.
如果你需要以下任一功能,可以选择安装 react-native-worklets:
- 在 iOS 上为
setPage提供动画。 不使用 worklets 时,iOS 的setPage会退化为无动画跳转。Android 无论如何都会进行动画。 - 保持在 UI 线程上的逐帧
onPageScroll回调。 当你的onPageScroll处理函数本身就是一个 worklet 时,它会在 UI 线程上每一帧同步运行,而不是切回 JS。即使不使用 worklets,回调仍然会触发——只是它会在 JS 线程上运行。
从 react-native-pager-view 迁移
通过从 @expo/ui/community/pager-view 导入 PagerView 来更新导入语句:
import PagerView from 'react-native-pager-view'; // 变为: import PagerView from '@expo/ui/community/pager-view';
在替换之前,你需要了解这些变化:
- 不支持
orientation="vertical"、keyboardDismissMode、overdrag和overScrollMode。 - 不提供
usePagerViewhook——请改用ref。 - 在 iOS 上,
onPageScroll和onPageScrollStateChanged仅在 iOS 18+ 上触发。
完整列表请参见 平台行为。
基本用法
import { useRef } from 'react'; import { Button, StyleSheet, Text, View } from 'react-native'; import PagerView, { type PagerViewRef } from '@expo/ui/community/pager-view'; export default function PagerViewExample() { const pagerRef = useRef<PagerViewRef>(null); return ( <View style={{ flex: 1 }}> <PagerView ref={pagerRef} style={{ flex: 1 }} initialPage={0} onPageSelected={event => { console.log('selected page', event.nativeEvent.position); }}> <View key="one" style={[styles.page, { backgroundColor: '#fde68a' }]}> <Text>第一页</Text> </View> <View key="two" style={[styles.page, { backgroundColor: '#bfdbfe' }]}> <Text>第二页</Text> </View> <View key="three" style={[styles.page, { backgroundColor: '#bbf7d0' }]}> <Text>第三页</Text> </View> </PagerView> <Button title="跳转到第 2 页" onPress={() => pagerRef.current?.setPage(1)} /> </View> ); } const styles = StyleSheet.create({ page: { flex: 1, alignItems: 'center', justifyContent: 'center' }, });
平台行为
Web 不受支持,并且在 web 上渲染 PagerView 会在运行时抛出异常。
| 功能 | Android | iOS |
|---|---|---|
| 最低平台版本 | 任意受支持版本 | iOS 17+ 支持分页。在 iOS 16 上,视图会水平滚动,但页面不会吸附 |
onPageScroll / onPageScrollStateChanged | 仅限 iOS 18+。在 iOS 17 上,它们永远不会触发,并且组件在挂载时会记录一条开发警告 | |
动画化 setPage | 原生 pager 动画 | 通过 react-native-worklets 运行。如果未安装该包,则回退为无动画跳转 |
layoutDirection | ||
offscreenPageLimit | ||
pageMargin |
相较于上游 react-native-pager-view 的其他差异:
- 不支持
orientation="vertical"、keyboardDismissMode、overdrag和overScrollMode。仅提供水平分页,其余选项会回退为平台 pager 的默认值。 - 不提供
usePagerViewhook。请使用PagerView的ref来访问setPage、setPageWithoutAnimation和setScrollEnabled。 setScrollEnabled会触发重新渲染,以便新值作为 prop 传递给原生视图。对于从非 React 上下文切换状态(例如基于 ref 的手势处理器)来说,它仍然很有用。borderRadius样式在两个平台上都会生效。在 Android 上,只有数值类型才会裁剪 pager。底层的 Compose 宿主会静默丢弃诸如'50%'之类的字符串值。
API
import PagerView from '@expo/ui/community/pager-view';
Component
Type: React.Element<PagerViewProps>
A drop-in replacement for react-native-pager-view. Renders a horizontally
paged view backed by Jetpack Compose's HorizontalPager on Android and
SwiftUI on iOS. Each child is treated as a separate page.
ReactNodePages of the pager. Each child is treated as a separate page and
stretched to fill the pager. Each child should have a stable key.
number • Default: 0Index of the page that is initially selected. Read once on mount;
later changes are ignored. To navigate after mount, call
ref.setPage() or ref.setPageWithoutAnimation().
string • Default: 'ltr'Layout direction for paging.
Acceptable values are: 'ltr' | 'rtl'
numberNumber of pages kept off-screen on each side of the visible page.
(event: PagerViewOnPageScrollEvent) => voidFires continuously while a swipe is in progress. The event's position
is the index of the leading visible page; offset is the fractional
progress toward the next page in the [0, 1) range.
Mark this handler with 'worklet' (requires react-native-worklets)
to run it synchronously on the UI thread every frame.
(event: PageScrollStateChangedEvent) => voidFires when the scroll state changes between idle, dragging,
and settling.
(event: PagerViewOnPageSelectedEvent) => voidFires when a page is fully selected. The event's position is the
index of the new page.
Ref<PagerViewRef>Ref handle exposing imperative setPage, setPageWithoutAnimation,
and setScrollEnabled methods.
boolean • Default: trueWhether the user can swipe between pages.
Types
Type: NativeSyntheticEvent<PagerViewOnPageScrollEventData>
Type: Readonly<{
offset: number,
position: number
}>
Type: NativeSyntheticEvent<PagerViewOnPageSelectedEventData>
Type: Readonly<{
position: number
}>
Ref handle for the PagerView component.
| Property | Type | Description |
|---|---|---|
| setPage | (selectedPage: number) => void | Animate the pager to the given page index. Out-of-range indices are
silently ignored. On iOS the animation requires |
| setPageWithoutAnimation | (selectedPage: number) => void | Jump to the given page index without an animation. |
| setScrollEnabled | (scrollEnabled: boolean) => void | Imperatively enable or disable user scrolling.
|
Type: NativeSyntheticEvent<PageScrollStateChangedEventData>
Type: Readonly<{
pageScrollState: 'idle' | 'dragging' | 'settling'
}>