React Native 安卓端 ScrollView 内嵌 Slider 滑动失效问题求助
问题根因
该问题由Android端原生触摸事件分发机制导致:横向ScrollView会默认拦截所有横向滑动类的触摸事件,你拖拽Slider的操作会被优先判定为ScrollView的翻页/滚动操作,事件被ScrollView消费后不会向下传递给Slider组件,因此出现点击有效、拖拽无效的现象。iOS端的触摸事件冒泡规则与Android存在差异,所以不会触发该异常。
解决方案
下面两个方案均可解决该问题:
- 方案1(兼容性最优,全版本RN适用):通过状态动态控制
ScrollView的滚动权限,Slider被触摸时暂时禁用ScrollView滚动,触摸结束后恢复滚动能力,修改后完整代码如下:
import React, { useState } from 'react'; import type {Node} from 'react'; import { SafeAreaView, ScrollView, View, Dimensions } from 'react-native'; import Slider from '@react-native-community/slider'; const Volume = ({onTouchStart, onTouchEnd, onTouchCancel}): Node => { return ( <Slider style={{width: 200, height: 40}} minimumValue={0} maximumValue={1} minimumTrackTintColor="#FFFFFF" maximumTrackTintColor="#000000" onTouchStart={onTouchStart} onTouchEnd={onTouchEnd} onTouchCancel={onTouchCancel} /> ); }; const App: () => Node = () => { const width = Dimensions.get('window').width; const slideStyle = { width, justifyContent: 'center', alignItems: 'center'} const [scrollEnabled, setScrollEnabled] = useState(true); return ( <SafeAreaView style={{ flex: 1 } }> <ScrollView horizontal pagingEnabled removeClippedSubviews={false} scrollEnabled={scrollEnabled} > <View style={{backgroundColor: 'red', ...slideStyle}}> <Volume onTouchStart={() => setScrollEnabled(false)} onTouchEnd={() => setScrollEnabled(true)} onTouchCancel={() => setScrollEnabled(true)} /> </View> <View style={{backgroundColor: 'blue', width, ...slideStyle}}> <Volume onTouchStart={() => setScrollEnabled(false)} onTouchEnd={() => setScrollEnabled(true)} onTouchCancel={() => setScrollEnabled(true)} /> </View> <View style={{backgroundColor: 'green', width, ...slideStyle}}> <Volume onTouchStart={() => setScrollEnabled(false)} onTouchEnd={() => setScrollEnabled(true)} onTouchCancel={() => setScrollEnabled(true)} /> </View> </ScrollView> </SafeAreaView> ); }; export default App;
- 方案2(改动量更小,RN 0.65+适用):直接给
Slider外层包裹一层View,阻止触摸事件冒泡到父级ScrollView,代码示例如下:
// 仅需修改Volume组件即可 const Volume = (): Node => { return ( <View onTouchStart={e => e.stopPropagation()}> <Slider style={{width: 200, height: 40}} minimumValue={0} maximumValue={1} minimumTrackTintColor="#FFFFFF" maximumTrackTintColor="#000000" /> </View> ); };
内容的提问来源于stack exchange,提问作者Anshul Kai
相关产品推荐
相关产品推荐

