React Native中如何让上层View触发onPress同时将触摸事件透传给下层视图
你之前设置pointerEvents="none"之后,上层视图会完全不接收所有触摸事件,所以onPress自然不会触发,不能用这个属性来实现同时响应的需求,可通过以下两种方案实现:
方案1:基于RN原生手势响应系统实现(无额外依赖)
不需要引入第三方库,通过RN自带的手势响应回调控制事件同时透传给下层ScrollView,自己实现点击逻辑判定即可:
import { useState } from 'react'; import { View, ScrollView, StyleSheet } from 'react-native'; const styles = StyleSheet.create({ containingTouchable: { position: 'absolute', top: 0, right: 0, left: 0, bottom: 0, backgroundColor: 'rgba(100,100,100,0.3)', zIndex: 999, // 确保上层视图在最前 }, }); const Component = () => { // 记录触摸起始信息,用于判断是否为点击 const [touchStartInfo, setTouchStartInfo] = useState(null); const handleTouchStart = (e) => { const { pageX, pageY, timestamp } = e.nativeEvent; setTouchStartInfo({ x: pageX, y: pageY, time: timestamp }); }; const handleTouchEnd = (e) => { if (!touchStartInfo) return; const { pageX, pageY, timestamp } = e.nativeEvent; // 判定规则:触摸时长小于200ms,偏移量小于10px则视为点击,可根据业务调整阈值 const duration = timestamp - touchStartInfo.time; const offsetX = Math.abs(pageX - touchStartInfo.x); const offsetY = Math.abs(pageY - touchStartInfo.y); if (duration < 200 && offsetX < 10 && offsetY < 10) { console.warn('pressed me'); } setTouchStartInfo(null); }; // 允许当前视图响应触摸 const onShouldSetResponder = () => true; // 允许下层视图同时响应触摸,不会拦截ScrollView的滚动事件 const onResponderTerminationRequest = () => false; return ( <> <View style={styles.containingTouchable} onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd} onShouldSetResponder={onShouldSetResponder} onResponderTerminationRequest={onResponderTerminationRequest} /> <ScrollView> {/* ScrollView原有内容 */} </ScrollView> </> ); };
方案2:使用react-native-gesture-handler实现(代码更简洁)
如果你项目中已经接入了react-native-gesture-handler,可以直接通过配置手势并发响应实现:
import { ScrollView, StyleSheet, View } from 'react-native'; import { Gesture, GestureDetector } from 'react-native-gesture-handler'; const styles = StyleSheet.create({ containingTouchable: { position: 'absolute', top: 0, right: 0, left: 0, bottom: 0, backgroundColor: 'rgba(100,100,100,0.3)', }, }); const Component = () => { const tapGesture = Gesture.Tap() .onEnd(() => { console.warn('pressed me'); }) // 允许点击手势和ScrollView的滚动手势同时响应 .simultaneousWithExternalGesture(ScrollView); return ( <> <GestureDetector gesture={tapGesture}> <View style={styles.containingTouchable} /> </GestureDetector> <ScrollView> {/* ScrollView原有内容 */} </ScrollView> </> ); };
内容的提问来源于stack exchange,提问作者Banky
相关产品推荐
相关产品推荐

