This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
This is documentation for the next SDK version. For up-to-date documentation, see the latest version (SDK 57).
BottomSheet
与 @gorhom/bottom-sheet 兼容的底部弹出层。
一个与 @gorhom/bottom-sheet API 兼容的 BottomSheet 组件。它封装了平台特定的 @expo/ui 原语:Android 上的 Jetpack Compose ModalBottomSheet 和 iOS 上的 SwiftUI BottomSheet。在 web 上,它使用 vaul 抽屉。
如果你需要对平台特定的样式、修饰器或布局行为进行更底层的控制,请直接使用原生原语。
安装
- npx expo install @expo/uiIf you are installing this in an existing React Native app, make sure to install expo in your project.
从 @gorhom/bottom-sheet 迁移
-
将以下导入更新为:
import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet';改为使用
@expo/ui/community/bottom-sheet:import BottomSheet, { BottomSheetView } from '@expo/ui/community/bottom-sheet'; -
此实现不需要
react-native-gesture-handler中的GestureHandlerRootView。如果应用的其他部分需要它,你可以保留。 -
不支持诸如
BottomSheetBackdrop、BottomSheetHandle、BottomSheetFooter、BottomSheetDraggableView、BottomSheetVirtualizedList、BottomSheetFlashList、useBottomSheetModal、useBottomSheetSpringConfigs和useBottomSheetTimingConfigs之类的组件和 hook 导出。为保持 API 兼容性,导出了一些相关的属性类型。
基本用法
import { useRef } from 'react'; import { Button, Text, View } from 'react-native'; import BottomSheet, { BottomSheetView } from '@expo/ui/community/bottom-sheet'; export default function BottomSheetExample() { const sheetRef = useRef<BottomSheet>(null); return ( <View style={{ flex: 1 }}> <Button title="打开" onPress={() => sheetRef.current?.snapToIndex(0)} /> <BottomSheet ref={sheetRef} snapPoints={['25%', '50%', '90%']} index={-1} onChange={index => { console.log('onChange', index); }} onClose={() => { console.log('已关闭'); }} enablePanDownToClose> <BottomSheetView style={{ flex: 1, padding: 24, alignItems: 'center' }}> <Text>底部抽屉内容</Text> </BottomSheetView> </BottomSheet> </View> ); }
BottomSheetModal
从 @gorhom/bottom-sheet 的 modal API 迁移时,请使用 BottomSheetModal。它会以关闭状态开始,并通过 present() 打开。
import { useRef } from 'react'; import { Button, Text, View } from 'react-native'; import { BottomSheetModal, BottomSheetView } from '@expo/ui/community/bottom-sheet'; export default function BottomSheetModalExample() { const modalRef = useRef<BottomSheetModal>(null); return ( <View style={{ flex: 1 }}> <Button title="Present" onPress={() => modalRef.current?.present()} /> <BottomSheetModal ref={modalRef} snapPoints={['50%', '90%']} enablePanDownToClose> <BottomSheetView style={{ padding: 24 }}> <Text>模态内容</Text> <Button title="Dismiss" onPress={() => modalRef.current?.dismiss()} /> </BottomSheetView> </BottomSheetModal> </View> ); }
动态尺寸
当未提供 snapPoints 时,底部弹窗默认会自动调整大小以适配其内容。请使用 BottomSheetView 作为底部弹窗内容的包装器。
import { useRef } from 'react'; import { Button, Text, View } from 'react-native'; import BottomSheet, { BottomSheetView } from '@expo/ui/community/bottom-sheet'; export default function DynamicBottomSheetExample() { const sheetRef = useRef<BottomSheet>(null); return ( <View style={{ flex: 1 }}> <Button title="打开" onPress={() => sheetRef.current?.present()} /> <BottomSheet ref={sheetRef} index={-1} enablePanDownToClose> <BottomSheetView style={{ padding: 24 }}> <Text>此弹窗会根据其内容自动调整大小。</Text> </BottomSheetView> </BottomSheet> </View> ); }
可滚动的 React Native 内容
底部弹窗支持将 React Native 的 FlatList 或 ScrollView(也支持像 FlashList 或 Legend List 这样的高性能列表)作为子组件来显示可滚动内容。启用 nestedScrollEnabled 后,列表会先滚动自身内容。到达顶部边缘后,剩余的拖动会移动弹窗。为了兼容 @gorhom/bottom-sheet,还导出了 BottomSheetFlatList 和 BottomSheetScrollView,但它们只是对 React Native 组件的简单重导出。
import { useRef } from 'react'; import { Button, FlatList, Text, View } from 'react-native'; import BottomSheet from '@expo/ui/community/bottom-sheet'; const DATA = Array.from({ length: 50 }, (_, i) => `Item ${i + 1}`); export default function BottomSheetScrollableExample() { const sheetRef = useRef<BottomSheet>(null); return ( <View style={{ flex: 1 }}> <Button title="打开" onPress={() => sheetRef.current?.snapToIndex(0)} /> <BottomSheet ref={sheetRef} snapPoints={['50%', '90%']} index={-1} enablePanDownToClose> <FlatList nestedScrollEnabled style={{ flex: 1 }} data={DATA} keyExtractor={item => item} contentContainerStyle={{ padding: 24 }} renderItem={({ item }) => <Text style={{ paddingVertical: 16 }}>{item}</Text>} /> </BottomSheet> </View> ); }
平台行为
@gorhom/bottom-sheet 以内联方式渲染在其父视图底部。该组件在 Android 和 iOS 上使用原生模态呈现,在 web 上使用抽屉覆盖层。
这种差异是有意为之。@gorhom/bottom-sheet 通过 react-native-gesture-handler 和 react-native-reanimated 自己管理手势与动画层,而 @expo/ui/community/bottom-sheet 则将这些行为委托给 Jetpack Compose、SwiftUI 和 web 抽屉原语。因此,该组件更适合模态底部弹窗流程,包括使用 BottomSheet API 而不是 BottomSheetModal 的调用场景。
| 功能 | Android | iOS | Web |
|---|---|---|---|
| 呈现方式 | Jetpack Compose 模态底部弹窗 | SwiftUI sheet | vaul 抽屉 |
| Snap 点 | 映射到部分展开和完全展开状态 | 支持提供的 snap 点 | 支持提供的 snap 点 |
未提供 snapPoints | 适配内容高度 | 适配内容高度 | 适配内容高度 |
| 向下拖动关闭 | 同时启用返回按钮和遮罩点击关闭 | 同时启用背景层点击关闭 | 启用抽屉关闭 |
| 持久化内联预览 | 不支持 | 不支持 | 不支持 |
信息 在 iOS 上,如果要在另一个底部弹窗之上再显示一个底部弹窗,应将第二个
BottomSheet嵌套在第一个弹窗的内容中,而不是并列放置。这是底层 SwiftUIsheet修饰符的限制。有关更多信息,请参阅 如何呈现多个 sheet。
支持的导出
| 导出 | 支持情况 | 说明 |
|---|---|---|
BottomSheet | Android 和 iOS 上为模态弹窗,web 上为抽屉 | |
BottomSheetModal | 以关闭状态开始,并通过 present() 打开 | |
BottomSheetModalProvider | 为兼容性直接渲染子元素 | |
BottomSheetView | 包裹底部弹窗内容 | |
BottomSheetScrollView | 重新导出 React Native 的 ScrollView | |
BottomSheetFlatList | 重新导出 React Native 的 FlatList | |
BottomSheetSectionList | 重新导出 React Native 的 SectionList | |
BottomSheetTextInput | 重新导出 React Native 的 TextInput | |
useBottomSheet | 从上下文中返回底部弹窗 ref 方法 | |
BottomSheetBackdrop | 原生底部弹窗或 web 抽屉会处理背景层 | |
BottomSheetHandle | 原生底部弹窗或 web 抽屉会处理拖拽指示器 | |
BottomSheetFooter | 该实现中没有对应功能 |
兼容性说明
- 支持
snapPoints、index、onChange、onClose、onDismiss、enablePanDownToClose和enableDynamicSizing。 handleComponent={null}会隐藏原生或 web 的拖拽指示器。自定义把手组件不会在原生平台上渲染。backgroundStyle在 web 上完全生效。在 Android 上,backgroundColor用于原生容器颜色。在 iOS 上,使用系统底部弹窗背景。- 动画、超额拖拽、内容拖动、把手拖动、键盘行为、自定义背景层、自定义背景、自定义页脚、动画值和分离式属性为兼容 API 而接受,但不会改变行为。
API
import BottomSheet from '@expo/ui/community/bottom-sheet';
Components
Type: React.Element<BottomSheetProps>
Bottom sheet component. Defaults to index={0} and opens at the first snap point on mount.
Props for the BottomSheet component. API-compatible with @gorhom/bottom-sheet where native platform behavior allows.
boolean • Default: trueWhether the sheet should automatically size to fit its content.
boolean • Default: falseWhether the sheet can be dismissed by panning down.
number • Default: 0Initial snap point index. Set to -1 to start closed.
(index: number) => voidCalled when the current snap point index changes.
() => voidAlias for onClose for BottomSheetModal compatibility.
Type: React.Element<BottomSheetProps>
Modal variant of BottomSheet. Starts closed and opens with present().
Type: React.Element<{
children: React.ReactNode
}>
Provider for BottomSheetModal. It renders children directly for API compatibility.
Type: React.Element<BottomSheetViewProps>
A wrapper for content inside a BottomSheet.
boolean • Default: trueWhether the sheet should automatically size to fit its content.
boolean • Default: falseWhether the sheet can be dismissed by panning down.
number • Default: 0Initial snap point index. Set to -1 to start closed.
(index: number) => voidCalled when the current snap point index changes.
() => voidAlias for onClose for BottomSheetModal compatibility.
Hooks
Returns the imperative methods for the nearest BottomSheet.
BottomSheetMethodsTypes
Imperative methods exposed by BottomSheet and BottomSheetModal refs.
| Property | Type | Description |
|---|---|---|
| close | () => void | Close the bottom sheet. |
| collapse | () => void | Snap to the minimum snap point. |
| dismiss | () => void | Dismiss the bottom sheet. |
| expand | () => void | Snap to the maximum snap point. |
| forceClose | () => void | Force close the bottom sheet. |
| present | () => void | Present the bottom sheet at the first snap point. |
| snapToIndex | (index: number) => void | Snap to a snap point by index. |
| snapToPosition | (position: string | number) => void | Snap to a pixel value or percentage position. |