Swiping gestures i.e. scrolling, pull to refresh, etc.
I'm pulling my hair out trying to make this work, I don't understand how apps like Facebook accomplish this so well. It seems like such a simple thing to implement but I cannot for the life of me figure it out.
FYI: I'm using a FlatList with Touchable components inside. I've been messing around with the FlatList props (on scroll, on scroll begin drag, on scroll end drag, etc) as well as the Touchable props (on press, on press in, on press delay in, etc).
What I want: On the Facebook app, the MOMENT I begin scrolling or pulling to refresh, tap feedback is disabled so it doesn't look like I clicked on a post. But at the same time the MOMENT I tap on a post, the tap feedback is super responsive. How is this done?
What I get: The moment I begin scrolling or pulling to refresh, the tap feedback is played even though I wanted to scroll/refresh. To fix this, I tried putting a pressDelayIn
of 50ms. But now, quickly tapping on a post doesn't play the feedback.
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>
);
}
CodePudding user response:
you can check this answer i think it will help you to resolve your problem.
I think pointerEvents
is the property you need to handle this.
this property controls whether the View can be the target of touch events.
https://stackoverflow.com/a/47890427/14221660
https://stackoverflow.com/a/39720112/14221660
CodePudding user response:
I definitely understand the frustration. I'd 1 ucup's suggestion to checkout react-native-gesture-handler. In the mean time, I disabled the TouchableOpacity
while scrolling, and dialed back the delayPressIn
and it seem to work pretty well. See what you think:
Add state to track canPress
export default function App() {
const [canPress, setCanPress] = useState(true); //
const [refreshing, setRefreshing] = useState(false);
...
Wire up to the 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>
Then just wire up to your TouchableOpacity
<TouchableOpacity
disabled={!canPress} //
activeOpacity={0.5}
delayPressIn={50} //
onPress={() => console.log(`Press id ${post.id}`)}>
...
Good luck!