文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何在React Native开发中防止滑动过程中的误触

2023-05-19 08:39

关注

一、问题背景

常见的情形是长列表中,在滑动过程中可能会出现误触到列表中的某一项的情形,对于用户使用非常不好的体验。

如下列表组件中,就会存在滑动过程中产生误触的情况。

import React from 'react';
import { 
  StyleSheet, Text, SafeAreaView,
  ScrollView,  View, TouchableOpacity, StatusBar,
} from 'react-native';
const App = () => {
  const list = Array.from(Array(100).keys());
  const onPress = (e) => {
    alert(1);
  };
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView style={styles.scrollView}>
        {list.map((item) => {
          return (
            <TouchableOpacity onPress={onPress}>
              <View style={styles.containerView}>
                <Text style={styles.text}>{item}+ item</Text>
              </View>
            </TouchableOpacity>
          );
        })}
      </ScrollView>
    </SafeAreaView>
  );
};
const styles = StyleSheet.create({
  container: { flex: 1, paddingTop: StatusBar.currentHeight },
  scrollView: { marginHorizontal: 20 },
  text: { fontSize: 1 },
  containerView: { backgroundColor: 'pink', marginTop: 20, height: 50 },
});
export default App;

上面长列表,在滚动的过程中可能会出现误触的问题。

二、解决思路

我们应该如何处理这种情形,可以考虑从点击事件上入手,考虑根据距离的移动来进行组织是否响应点击事件

通过查看官方文档,我们能够发现点击时间在点击按下和抬起的过程中有一个过程回调,我们就可以利用这个回调进行处理误触了,有兴趣的小伙伴可以看看这块官方说明

由于点击事件执行过程原理

在按下 onPressIn 后,将会出现如下两种情况的一种:

用户移开手指,依次触发onPressOut 和onPress事件。

按压持续 500 毫秒以上,触发onLongPress 事件。(onPressOut 在移开手后依旧会触发。)

可以通过监听点击事件的方式来监听按钮点击,那我们来简单实现一个避免误触的方案

其中的核心原理就是点击事件的整个过程,总结来说就是下面的三个点击过程

  onPressOut={(event) => {
    const [startX, startY] = [
      event.nativeEvent.pageX,
      event.nativeEvent.pageY,
    ];
    const currentTime = new Date().getTime();
    const shouldReject =
      (Math.abs(pressInPointRef.current.startX - startX) >
        pointDistance ||
        Math.abs(pressInPointRef.current.startY - startY) >
          pointDistance) &&
      (currentTime - pressInTime.current) < pointMinTimeSpace;
    console.log('shouldReject', shouldReject);
    shouldReject && event?.preventDefault?.();
  }}
  onPress={(event) => {
    if (event?.isDefaultPrevented?.()) return;
    onclick && onclick();
  }}
  onPressIn={(event) => {
    pressInPointRef.current.startX = event.nativeEvent.pageX;
    pressInPointRef.current.startY = event.nativeEvent.pageY;
    pressInTime.current = new Date().getTime();
  }}

当发生触摸时,通过onPressIn事件记录位置和获取事件戳,当指头触摸弹起时,通过onPressOut事件记录并且对比按下时的位置和按下时的时间,是否满足响应当前点击的条件,如果不满足响应,则使用event?.preventDefault?.()阻止其继续响应,最后根据onPress事件中if (event?.isDefaultPrevented?.()) return;判断该如何响应这次触摸点击,这就是整个过程。

pressInTime

调整按压时间区间,在按下时和抬起间隔小于该时间,则认为是误触,这个和距离区间(pointDistance)一起确定是否误触

pointDistance

调整按下和抬起时之间的距离,在按下时和抬起间隔小于该距离,则认为是误触,这个和按压时间(pressInTime)区间一起确定是否误触

调整显示组件

其中TouchableOpacity组件可以更换为能够响应点击事件的任何组件,下面是官方列出的被引用到的组件,都能够使用这种方式处理误触。

 Button
 PanResponder
 Pressable
 ScrollView
 Text
 TextInput
 TouchableHighlight
 TouchableOpacity
 TouchableNativeFeedback
 TouchableWithoutFeedback
 View

针对以上情况,能够将其应用到业务不同的误触情况下,下面是整理之后,完整的代码,根据以上情况可以再次进行组件封装,适配自己业务组件的调整。

const App = () => {
  const list = Array.from(Array(100).keys());
  const pressInPointRef = useRef({ startX: 0, startY: 0 });
  const。pressInTime = useRef(0);
  const pointDistance = 100;
  const pointMinTimeSpace = 1000;
  const onclick = () => {
    console.log('按钮被点击...');
    alert('按钮被点击...')
  };
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView style={styles.scrollView}>
        {list.map((item) => {
          return (
            <TouchableOpacity
              onPressOut={(event) => {
                const [startX, startY] = [
                  event.nativeEvent.pageX,
                  event.nativeEvent.pageY,
                ];
                const currentTime = new Date().getTime();
                const shouldReject =
                  (Math.abs(pressInPointRef.current.startX - startX) >
                    pointDistance ||
                    Math.abs(pressInPointRef.current.startY - startY) >
                      pointDistance) &&
                  (currentTime - pressInTime.current) < pointMinTimeSpace;
                console.log('shouldReject', shouldReject);
                shouldReject && event?.preventDefault?.();
              }}
              onPress={(event) => {
                if (event?.isDefaultPrevented?.()) return;
                onclick && onclick();
              }}
              onPressIn={(event) => {
                pressInPointRef.current.startX = event.nativeEvent.pageX;
                pressInPointRef.current.startY = event.nativeEvent.pageY;
                pressInTime.current = new Date().getTime();
              }}>
              <View style={styles.containerView}>
                <Text style={styles.text}>{item}+ line</Text>
              </View>
            </TouchableOpacity>
          );
        })}
      </ScrollView>
    </SafeAreaView>
  );
};

三、总结整理

到此这篇关于如何在React Native开发中防止滑动过程中的误触的文章就介绍到这了,更多相关React Native防止滑动误触内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯