如何修改@gorhom/bottom-sheet代码实现触摸手势上下滑动
解决@gorhom/bottom-sheet触摸手势滑动问题
针对你的需求,要让@gorhom/bottom-sheet支持触摸上下滑动,需检查依赖集成和组件配置,以下是具体修改步骤:
1. 确保react-native-gesture-handler正确集成
在App入口文件(如App.js或index.js)中,用GestureHandlerRootView包裹整个应用,这是手势识别的基础:
import { GestureHandlerRootView } from 'react-native-gesture-handler'; export default function App() { return ( <GestureHandlerRootView style={{ flex: 1 }}> {/* 你的导航或根组件 */} </GestureHandlerRootView> ); }
2. 验证react-native-reanimated的Babel配置
在项目根目录的babel.config.js中,确保添加reanimated插件且放在最后一位:
module.exports = { presets: ['module:metro-react-native-babel-preset'], plugins: ['react-native-reanimated/plugin'], };
修改后需重启Metro服务,避免缓存导致配置不生效。
3. 修改BottomSheet组件代码
关键调整点:
- 用
BottomSheetScrollView替换内部原生ScrollView,避免手势冲突 - 通过
useMemo定义snapPoints,保证配置稳定性 - 可选添加
enablePanDownToClose,支持向下滑动关闭Sheet
修改后的完整组件代码:
import React, { useState, useCallback, useRef, useMemo } from 'react'; import { View, StyleSheet, Text } from 'react-native'; import { MaterialIcons } from '@expo/vector-icons'; import BottomSheet, { BottomSheetView, BottomSheetScrollView } from "@gorhom/bottom-sheet"; export const Profile = () => { const sheetRef = useRef(null); // 用useMemo缓存snapPoints,避免重复创建 const snapPoints = useMemo(() => ['25%', '50%', '90%'], []); const handleSheetChange = useCallback((index) => { console.log('handleSheetChanges', index); }, []); const handleSnapPress = useCallback((index) => { sheetRef.current?.snapToIndex(index); }, []); const handleClosePress = useCallback(() => { sheetRef.current?.close(); }, []); // 替换原生ScrollView为BottomSheetScrollView,解决手势冲突 const renderItem = useCallback(() => ( <BottomSheetScrollView contentContainerStyle={styles.whiteBoxContent}> <View style={styles.infoContainer}> <Text style={styles.name}>{card.name},</Text> <Text style={styles.age}>{card.age}</Text> <View style={styles.ratingContainer}> <MaterialIcons name="star-rate" size={36} color="#5285F4" style={styles.starIcon} /> {roundedRate && <Text style={styles.showRating}>{roundedRate}</Text>} </View> </View> </BottomSheetScrollView> ), [card, roundedRate]); // 省略其他无关逻辑... return ( <View style={styles.container}> <BottomSheet ref={sheetRef} index={1} snapPoints={snapPoints} onChange={handleSheetChange} enablePanDownToClose={true} // 可选:允许向下滑动关闭Sheet enableDynamicSizing={true} // 可选:根据内容动态调整Sheet尺寸 > <BottomSheetView style={styles.contentContainer}> {renderItem()} </BottomSheetView> </BottomSheet> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f0f0f0', }, contentContainer: { flex: 1, padding: 16, }, whiteBoxContent: { gap: 12, }, infoContainer: { flexDirection: 'row', alignItems: 'center', gap: 8, }, name: { fontSize: 18, fontWeight: 'bold', }, age: { fontSize: 16, }, ratingContainer: { flexDirection: 'row', alignItems: 'center', marginLeft: 8, }, starIcon: { marginRight: 4, }, showRating: { fontSize: 16, color: '#5285F4', }, });
4. 重启服务测试
修改完成后执行以下步骤:
- 关闭当前Metro服务
- 重置缓存并重启Metro:
npx react-native start --reset-cache - 重新运行项目:
npx react-native run-android或npx react-native run-ios
常见问题排查
- 手势仍不生效:检查
GestureHandlerRootView是否正确包裹根组件,确认依赖版本兼容(你的版本组合是兼容的) - 内部滚动与Sheet手势冲突:确保使用
BottomSheetScrollView而非原生ScrollView,它会自动处理手势优先级
内容的提问来源于stack exchange,提问作者Jtigg
相关产品推荐
相关产品推荐

