react-native-bottom-sheet如何实现下滑手势关闭底部表单?
gorhom/react-native-bottom-sheet 下滑手势关闭实现方案
核心靠组件内置配置项即可实现,不需要额外手写手势监听,具体实现方式如下:
核心配置项说明
给BottomSheet或者BottomSheetModal组件配置以下属性即可开启下滑关闭能力:
enablePanDownToClose={true}:这是开启下滑关闭的核心开关,默认值为false,未开启时下滑只会在配置的snap档位之间切换,不会触发关闭逻辑onClose:关闭事件回调,在这里处理表单隐藏、状态重置等业务逻辑- 可选自定义调整项:
dragToCloseThreshold:下滑触发关闭的阈值,取值范围0~1,默认值0.3,即下滑距离超过当前表单高度的30%就会自动触发关闭,值越小关闭动作越灵敏closeDuration:关闭动画时长,单位ms,默认400ms,可根据需要调整动画快慢
手势冲突处理
如果表单内部放了ScrollView/FlatList/SectionList等滚动组件,不要使用React Native原生提供的滚动组件,必须替换为库内置封装的对应组件:
- 替换原生
ScrollView为BottomSheetScrollView - 替换原生
FlatList为BottomSheetFlatList - 替换原生
SectionList为BottomSheetSectionList
否则会出现滚动区域手势抢占,下滑无法触发关闭的问题。
另外不要随意修改enableContentPanningGesture属性,该属性默认值为true,手动设为false后只有拖拽表单顶部的handle区域才能触发下滑,内容区拖拽不会响应关闭手势。
可运行代码示例
import React, { useCallback, useMemo, useRef } from 'react'; import { View, Text, StyleSheet, Button } from 'react-native'; import BottomSheet, { BottomSheetScrollView } from '@gorhom/bottom-sheet'; export default function BottomSheetDemo() { const sheetRef = useRef<BottomSheet>(null); // 定义表单展开的档位高度,不需要额外加0(关闭位) const snapPoints = useMemo(() => ['35%', '75%'], []); const handleSheetClose = useCallback(() => { // 在这里写关闭后的业务逻辑,比如控制表单卸载、重置表单状态等 console.log('底部表单已通过下滑手势关闭'); }, []); return ( <View style={styles.pageContainer}> <Button title="唤起底部表单" onPress={() => sheetRef.current?.snapToIndex(0)} /> <BottomSheet ref={sheetRef} index={-1} // 初始设为-1即默认隐藏 snapPoints={snapPoints} enablePanDownToClose={true} dragToCloseThreshold={0.25} closeDuration={280} onClose={handleSheetClose} > <BottomSheetScrollView contentContainerStyle={styles.sheetContent}> <Text style={styles.tipText}>向下拖拽表单即可触发关闭</Text> {/* 其他业务内容 */} </BottomSheetScrollView> </BottomSheet> </View> ); } const styles = StyleSheet.create({ pageContainer: { flex: 1, padding: 16, backgroundColor: '#fff' }, sheetContent: { padding: 20, }, tipText: { fontSize: 16, textAlign: 'center', color: '#333' } });
常见踩坑
- 如果使用
BottomSheetModal做模态弹窗,配置逻辑完全一致,开启enablePanDownToClose后下滑会自动触发模态关闭,不需要手动调用ref的close方法 - 不要给BottomSheet的父容器设置
pointerEvents="none",会导致手势无法被组件识别 - 如果父容器是绝对定位,要确保BottomSheet的层级足够高,不会被其他元素遮挡手势响应区域
内容的提问来源于stack exchange,提问作者universe11
相关产品推荐
相关产品推荐

