【react native】ScrollView的触摸事件与TouchableWithoutFeedback的点击事件冲突

需求背景

使用 ScrollView 组件实现轮播图效果,该轮播图可以自动向右滑动。有下面两个需求:

(1)希望用户左右点击的时候,视图可以向左/向右滚动;

(2)希望用户触摸在屏幕的时候,轮播图不自动滚动,放开的时候重新计时5秒后向右滚动;

(3)在轮播视图内有一个按钮,希望我们在点击按钮并弹出弹窗的时候,轮播图停止计时,弹窗关闭后再重新计时。

需求分析

(1)我们可以使用 TouchableWithoutFeedback 组件,分别覆盖左右视图,当触发onPress的时候进行翻页。

(2)可以使用 ScrollViewonTouchStartonTouchEnd 事件,分别表示触摸开始和触摸结束时候的回调。

(3)事件的回调顺序是: onTouchStart > onPress > onTouchEnd ,所以下面的这种写法会导致,当点击share按钮的时候,打印如下:

onTouchStart
click button, start to stop timer
onTouchEnd
// 执行完异步操作后会打印
start to start timer

但我们希望的是,能够打印如下:

onTouchStart
click button, start to stop timer
// onTouchEnd 不打印
// 执行完异步操作后会打印
start to start timer
state = {
   
  scrollViewTouchable: true,
};

handleSharePress = async() => {
   
  // 停止定时器
  console.log('click button, start to stop timer');
  this.handleStopTimer();

  // 处理 "Share" 按钮的逻辑
  // await ....

  // 打开定时器
  console.log('start to start timer');
  this.handleStartTimer();
};

render() {
   
  const {
    scrollViewTouchable } = this.state;

  return (
    <View>
      <ScrollView
        onTouchStart={
   scrollViewTouchable ? ()=>{
   this.handleStartTimer(); console.log('onTouchStart')} : undefined}
        onTouchEnd={
   scrollViewTouchable ? ()=>{
   this.handleStopTimer(); console.log('onTouchEnd')} : undefined}
        // 其他属性...
      >
        {
   /* ScrollView 内容 */}

        <TouchableOpacity
          onPress={
   this.handleSharePress}
        >
          <View style={
   styles.shareButton}>
            {
   /* Share 按钮内容 */}
          </View>
        </TouchableOpacity>
      </ScrollView>
    </View>
  );
}

解决方法

通过阻止默认事件的方式好像不能解决上述问题,因为 TouchableWithoutFeedback 组件不会阻止事件冒泡到父组件。

所以我们考虑用一个state变量来控制 ScrollView 组件的触摸事件是否可用。在点击 “Share” 按钮时,将状态变量设置为 false,在 onPress 事件完成后,将状态变量设置回 true。

state = {
   
  scrollViewTouchable: true,
};

handleSharePress = async() => {
   
  this.setState({
    scrollViewTouchable: false });

  // 处理 "Share" 按钮的逻辑
  // await...

  this.setState({
    scrollViewTouchable: true });
};

render() {
   
  const {
    scrollViewTouchable } = this.state;

  return (
    <View>
      <ScrollView
        onTouchStart={
   scrollViewTouchable ? this.handleStartTimer : undefined}
        onTouchEnd={
   scrollViewTouchable ? this.handleStopTimer : undefined}
        // 其他属性...
      >
        {
   /* ScrollView 内容 */}

        <TouchableOpacity
          onPress={
   this.handleSharePress}
        >
          <View style={
   styles.shareButton}>
            {
   /* Share 按钮内容 */}
          </View>
        </TouchableOpacity>
      </ScrollView>
    </View>
  );
}

相关推荐

  1. 阻止div事件冒泡

    2024-02-07 05:58:05       10 阅读
  2. 事件触发事件捕获事件冒泡(js问题)

    2024-02-07 05:58:05       46 阅读
  3. vue触发真实 事件 跟用户行为一致

    2024-02-07 05:58:05       21 阅读
  4. Android --- 布局事件

    2024-02-07 05:58:05       15 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-07 05:58:05       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-07 05:58:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-07 05:58:05       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-07 05:58:05       20 阅读

热门阅读

  1. 2.6作业

    2024-02-07 05:58:05       27 阅读
  2. 安装nodejs2011并配置npm仓库

    2024-02-07 05:58:05       34 阅读
  3. VOL_常用记录!!

    2024-02-07 05:58:05       30 阅读
  4. 嵌入式硬件工程师与嵌入式软件工程师

    2024-02-07 05:58:05       41 阅读
  5. Lua可变参数函数

    2024-02-07 05:58:05       33 阅读
  6. 【计算机视觉】浅谈计算机视觉中的Transformer

    2024-02-07 05:58:05       29 阅读
  7. ubuntu22.04@laptop OpenCV Get Started: 003_image_resizing

    2024-02-07 05:58:05       38 阅读