React Native: 如何在执行滑动手势时正确禁用可点击反馈?

5

滑动手势,如滚动、下拉刷新等。

我正在绞尽脑汁地使其工作,我不明白Facebook这样的应用程序是如何做到这么好的。它似乎是一个很简单的实现,但我无论如何也想不出来。

FYI:我正在使用带有内部Touchable组件的FlatList。我一直在调整FlatList属性(on scroll、on scroll begin drag、on scroll end drag等)以及Touchable属性(on press、on press in、on press delay in等)。

我的目标: 在Facebook应用程序上,我开始滚动或下拉刷新的时候,点击反馈被禁用,所以它看起来像我没有点击过任何内容。但是当我点击帖子的时候,它的点击反馈又变得非常敏感。这是怎么做到的?

我的问题: 我一开始滚动或下拉刷新的瞬间,点击反馈就会播放,尽管我想要滚动/刷新。为了解决这个问题,我尝试将pressDelayIn设置为50毫秒。但现在,快速点击帖子时就不会再播放反馈了。

App.js

export default function App() {
  const [refreshing, setRefreshing] = useState(false);
  const [posts, setPosts] = useState([
    {
      id: 1,
      username: '@somedude',
      body: 'This is the best app ever, wow.',
    },
    {
      id: 2,
      username: '@doggo',
      body: 'Woof woof. Woof woof woof! Woof... Woof woof? Woof!',
    },
  ]);

  const onRefresh = () => {
    setRefreshing(true);
    setTimeout(() => setRefreshing(false), 1000);
  }

  return (
    <SafeAreaView style={styles.container}>
      <FlatList
        data={posts}
        renderItem={({ item }) => <Post post={item} />}
        keyExtractor={item => item.id}
        refreshing={refreshing}
        onRefresh={onRefresh}
      />
    </SafeAreaView>
  );
}

Post.js

export const Post = ({ post }) => {
  return (
  <TouchableOpacity
    activeOpacity={0.5}
    onPress={() => console.log(`Press id ${post.id}`)}
  >
    <View style={styles.postPontainer}>
      <View style={{ marginBottom: 5 }}>
        <Text>{post.username}</Text>
      </View>
      <View style={styles.textContainer}>
        <Text>{post.body}</Text>
      </View>
    </View>
  </TouchableOpacity>
  );
}

1
我认为Facebook使用react-native-gesture-handler来处理反馈和滑动手势。 https://docs.swmansion.com/react-native-gesture-handler/docs/api/components/touchables 或者他们可能使用Pressable。 https://reactnative.dev/docs/pressable - ucup
2个回答

2
我完全理解您的沮丧情绪。我赞同ucup的建议,去查看react-native-gesture-handler。与此同时,我在滚动时禁用了TouchableOpacity,并降低了delayPressIn,似乎效果还不错。看看您觉得怎么样:

添加状态来追踪canPress

export default function App() {
  const [canPress, setCanPress] = useState(true); //
  const [refreshing, setRefreshing] = useState(false);
  ...

连接FlatList

<SafeAreaView style={styles.container}>
    <FlatList
      data={posts}
      onScrollBeginDrag={() => setCanPress(false)} //
      onScrollEndDrag={() => setCanPress(true)} //
      renderItem={({item}) => <Post post={item} canPress={canPress} />} //
      keyExtractor={item => item.id}
      refreshing={refreshing}
      onRefresh={onRefresh}
    />
</SafeAreaView>

然后只需将代码连接到您的TouchableOpacity即可。
<TouchableOpacity
      disabled={!canPress} //
      activeOpacity={0.5}
      delayPressIn={50} //
      onPress={() => console.log(`Press id ${post.id}`)}>
      ...

祝你好运!


onScrollEndDrag 会稍微晚一些触发(为什么呢?),所以这个方法没有那么顺畅地工作。 - OneTuskedMario

2

我认为您可以查看这个答案,它会帮助您解决问题。

我认为pointerEvents是您需要处理此问题的属性。此属性控制视图是否可以成为触摸事件的目标。

参考1

参考2


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接