Reputation: 832
I have a simple screen with components like this:
<Parent onLongPress={/* do something */}>
<Child onPress={/* do something */} />
<Child onPress={/* do something */} />
<Parent>
I would like any long press on anything within <Parent>
to trigger Parent.onLongPress
, and short press of children to trigger the correspondant Child.onPress
. I learned from the documentation that the parent view can use View.props.onStartShouldSetResponderCapture={(event) => true}
to be the one handling the event, but I cannot find a way to do this only for long press events and not all touch events. I initially expected I would be able to use the event type in onStartShouldSetResponderCapture
but it seems to always be set to undefined
.
I created a Snack if someone wants to try out: https://snack.expo.io/@dgellow/arrogant-strawberries.
Upvotes: 2
Views: 2293
Reputation: 3653
Use LongPressGestureHandler
from react-native-gesture-handler
to capture long press event on the parent component.
Before
<Button // custom component
style={styles.container}
onLongPress={() => {
// long press handler
}}
>
{children} // with `onPress`
</Button>
);
After
import {
LongPressGestureHandler,
State,
} from 'react-native-gesture-handler';
...
...
<LongPressGestureHandler
onHandlerStateChange={({ nativeEvent }) => {
if (nativeEvent.state === State.ACTIVE) {
// long press handler
}
}}
>
<View style={styles.container}>
{children} // with `onPress`
</View>
</LongPressGestureHandler>
Please note that the direct descendant of LongPressGestureHandler
should be a View
.
I almost go with context approach due to multiple deeply nested children that needed to call the onLongPress
function passed around as props.
If you are using react-navigation
, you are using react-native-gesture-handler
already.
Upvotes: 4
Reputation: 6584
I had the same problem here, ideally the child would "release" its hold on the capture of a press event after onPress
passes and let the parent's onLongPress
take over, but I've not found a way to do that.
The solution that worked in my instance was to add the same method for onLongPress
to the parent and the child, so if the child takes over, it uses the method passed to it, and if not then the parent calls the method.
Note I've got this working in my codebase, but not tried the specific example below:
const onLongPress = () => alert("long press!");
const onPress = () => alert("short press!");
return (
<Parent onLongPress={onLongPress}>
<Child onLongPress={onLongPress} onPress={onPress} />
<Child onLongPress={onLongPress} onPress={onPress} />
<Parent>
);
If the child component you want to add the onLongPress
& onPress
to is further down the Native DOM tree, then you can just keep passing that function down (though it does feel a bit messy if it's many levels nested deep, but I've found no alternative).
Upvotes: 2