如何在React?Native開發(fā)中防止滑動過程中的誤觸
一、問題背景
常見的情形是長列表中,在滑動過程中可能會出現(xiàn)誤觸到列表中的某一項的情形,對于用戶使用非常不好的體驗。
如下列表組件中,就會存在滑動過程中產(chǎn)生誤觸的情況。
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;上面長列表,在滾動的過程中可能會出現(xiàn)誤觸的問題。
二、解決思路
我們應該如何處理這種情形,可以考慮從點擊事件上入手,考慮根據(jù)距離的移動來進行組織是否響應點擊事件
通過查看官方文檔,我們能夠發(fā)現(xiàn)點擊時間在點擊按下和抬起的過程中有一個過程回調,我們就可以利用這個回調進行處理誤觸了,有興趣的小伙伴可以看看這塊官方說明
由于點擊事件執(zhí)行過程原理
- onPressIn 在按壓時被調用。
- onPressOut 在按壓動作結束后被調用。
在按下 onPressIn 后,將會出現(xiàn)如下兩種情況的一種:
用戶移開手指,依次觸發(fā)onPressOut 和onPress事件。
按壓持續(xù) 500 毫秒以上,觸發(fā)onLongPress 事件。(onPressOut 在移開手后依舊會觸發(fā)。)

可以通過監(jiān)聽點擊事件的方式來監(jiān)聽按鈕點擊,那我們來簡單實現(xiàn)一個避免誤觸的方案
其中的核心原理就是點擊事件的整個過程,總結來說就是下面的三個點擊過程
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();
}}當發(fā)生觸摸時,通過onPressIn事件記錄位置和獲取事件戳,當指頭觸摸彈起時,通過onPressOut事件記錄并且對比按下時的位置和按下時的時間,是否滿足響應當前點擊的條件,如果不滿足響應,則使用event?.preventDefault?.()阻止其繼續(xù)響應,最后根據(jù)onPress事件中if (event?.isDefaultPrevented?.()) return;判斷該如何響應這次觸摸點擊,這就是整個過程。
pressInTime
調整按壓時間區(qū)間,在按下時和抬起間隔小于該時間,則認為是誤觸,這個和距離區(qū)間(pointDistance)一起確定是否誤觸
pointDistance
調整按下和抬起時之間的距離,在按下時和抬起間隔小于該距離,則認為是誤觸,這個和按壓時間(pressInTime)區(qū)間一起確定是否誤觸
調整顯示組件
其中TouchableOpacity組件可以更換為能夠響應點擊事件的任何組件,下面是官方列出的被引用到的組件,都能夠使用這種方式處理誤觸。
Button
PanResponder
Pressable
ScrollView
Text
TextInput
TouchableHighlight
TouchableOpacity
TouchableNativeFeedback
TouchableWithoutFeedback
View
針對以上情況,能夠將其應用到業(yè)務不同的誤觸情況下,下面是整理之后,完整的代碼,根據(jù)以上情況可以再次進行組件封裝,適配自己業(yè)務組件的調整。
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>
);
};三、總結整理
- 解決這次觸摸,主要是使用點擊事件本身的一個響應機制,在中間通過記錄狀態(tài)值的方式去處理
- 使用到的方法涉及到按下時、抬起時、按下這三個過程
- 通用功能組件需要進行封裝,以達到業(yè)務功能上的適配
到此這篇關于如何在React Native開發(fā)中防止滑動過程中的誤觸的文章就介紹到這了,更多相關React Native防止滑動誤觸內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
React Hooks獲取數(shù)據(jù)實現(xiàn)方法介紹
這篇文章主要介紹了react hooks獲取數(shù)據(jù),文中給大家介紹了useState dispatch函數(shù)如何與其使用的Function Component進行綁定,實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2022-10-10

