react native scrollview手势冲突

背景
在使用scrollview或者listview时,一般有两种情况会出现手势冲突

  • scrollview在一个touch的内部
  • scrollview包裹一个touch
    上面我们只考虑了一个scrollview和一个touch的情况,而多个scrollview和多个touch的情况可以进行类比。

当一个scrollview包裹一个touch时,造成的冲突一般是touch响应时scrollview也会有响应,这时禁止scrollview的滚动即可,下面我们将说明一下如何解决scrollview在一个touch内部造成的手势冲突

问题
当一个scrollview在一个touch内部时,scrollview将得不到任何事件(android上可能好一点儿),示例代码如下:

export default class scrollPan extends Component {
    constructor(props){
        super(props);
        this.wrapperPanResponder = PanResponder.create({
            onStartShouldSetPanResponder: (e, g) => true,
            onPanResponderGrant: () => {
                console.log('GRANTED TO WRAPPER');
            },
            onPanResponderMove: (evt, gestureState) => {
                console.log('WRAPPER MOVED');
            }
        });

        this.scollerPanResponder = PanResponder.create({
            onStartShouldSetPanResponder: (e, g) => true,
            onPanResponderGrant: () => {
                console.log('GRANTED TO SCROLLER');
            },
            onPanResponderMove: (evt, gestureState) => {
                console.log('SCROLLER MOVED');
            }
        });
    }
    render() {
        return (
            <View style={styles.container} {...this.wrapperPanResponder.panHandlers}>
              <ScrollView onScroll={() => console.log('scrolled')} style={{maxHeight: 350}} {...this.scollerPanResponder.panHandlers}>
                <Text style={{fontSize:96}}>Scroll this</Text>
                <Text style={{fontSize:96}}>Scroll this</Text>
                <Text style={{fontSize:96}}>Scroll this</Text>
                <Text style={{fontSize:96}}>Scroll this</Text>
                <Text style={{fontSize:96}}>Scroll this</Text>
              </ScrollView>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
});

运行代码后,点击与滑动scrollview都没有响应,为父touch加上手势放行或者只拦截点击事件,不拦截move事件也解决不了问题

解决办法
将panResonder改为绝对布局,即可解决冲突

export default class scrollPan extends Component {
    constructor(props){
        super(props);
        this.wrapperPanResponder = PanResponder.create({
            onStartShouldSetPanResponder: (e, g) => true,
            onPanResponderGrant: () => {
                console.log('GRANTED TO WRAPPER');
            },
            onPanResponderMove: (evt, gestureState) => {
                console.log('WRAPPER MOVED');
            }
        });

        this.scollerPanResponder = PanResponder.create({
            onStartShouldSetPanResponder: (e, g) => true,
            onPanResponderGrant: () => {
                console.log('GRANTED TO SCROLLER');
            },
            onPanResponderMove: (evt, gestureState) => {
                console.log('SCROLLER MOVED');
            }
        });
    }
    render() {
        return (
            <View style={styles.container}>
              <View style={styles.pan_container} {...this.wrapperPanResponder.panHandlers} />
              <ScrollView onScroll={() => console.log('scrolled')} style={styles.scroll_view} {...this.scollerPanResponder.panHandlers}>
                <Text style={{fontSize:96}}>Scroll this</Text>
                <Text style={{fontSize:96}}>Scroll this</Text>
                <Text style={{fontSize:96}}>Scroll this</Text>
                <Text style={{fontSize:96}}>Scroll this</Text>
                <Text style={{fontSize:96}}>Scroll this</Text>
              </ScrollView>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    pan_container: {
        ...StyleSheet.absoluteFillObject,
        backgroundColor: 'blue'
    },
    scroll_view: {
        backgroundColor: 'teal',
        maxHeight: 350
    }
});

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 122,440评论 15 533
  • 在开发过程中,大家或多或少的都会碰到令人头疼的手势冲突问题,正好前两天碰到一个类似的bug,于是借着这个机会了解了...
    闫仕伟阅读 988评论 2 8
  • 好奇触摸事件是如何从屏幕转移到APP内的?困惑于Cell怎么突然不能点击了?纠结于如何实现这个奇葩响应需求?亦或是...
    Lotheve阅读 18,384评论 39 321
  • 在iOS开发中经常会涉及到触摸事件。本想自己总结一下,但是遇到了这篇文章,感觉总结的已经很到位,特此转载。作者:L...
    WQ_UESTC阅读 1,356评论 0 4
  • 写在前面:我本科财务管理专业,英语过了六级,日常交流没有问题,并且最近有开始有目的的练习口语,所以自认为满足招聘要...
    Minta翁阅读 28评论 1 0