How to prevent event bubbling when clicking on an item? #469
-
Hello, and thank you for the great library! I've run into a question about how to block event bubbling when clicking on child elements (items) that are controlled by "reanimated". The situation is as follows: I'm using the "reanimated-color-picker" library inside a list item, and when I long-press on the color picker, a drag event is triggered. This situation only occurs on Android. Here is a code example: import { useState } from 'react';
import { View } from 'react-native';
import Sortable, { type SortableFlexDragEndParams } from 'react-native-sortables';
import Animated, { useAnimatedRef } from 'react-native-reanimated';
import ColorPicker, { Panel3 } from 'reanimated-color-picker';
const scrollableRef = useAnimatedRef<Animated.ScrollView>();
const [color1, setColor1] = useState('#ffffff');
const [color2, setColor2] = useState('#ff0000');
return (
<Animated.ScrollView
ref={scrollableRef}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
>
<Sortable.Flex
gap={20}
dragActivationDelay={600}
scrollableRef={scrollableRef}
enableActiveItemSnap={false}
onDragEnd={handleDragEnd}
hapticsEnabled
>
<View style={{ backgroundColor: '#aaa', padding: 20 }}>
<View style={{ paddingBlock: 12, width: 120 }}>
<ColorPicker
value={color1}
thumbShape="circle"
thumbSize={18}
onCompleteJS={(color) => setColor1(color.hex)}
onChangeJS={(color) => setColor1(color.hex)}
>
<Panel3 centerChannel="saturation" />
</ColorPicker>
</View>
</View>
<View style={{ backgroundColor: '#aaa', padding: 20 }}>
<View style={{ paddingBlock: 12, width: 120 }}>
<ColorPicker
value={color2}
thumbShape="circle"
thumbSize={18}
onCompleteJS={(color) => setColor2(color.hex)}
onChangeJS={(color) => setColor2(color.hex)}
>
<Panel3 centerChannel="saturation" />
</ColorPicker>
</View>
</View>
</Sortable.Flex>
</Animated.ScrollView>
); I'm trying to make the drag & drop activate only on a long press on the area with the "#aaa" background, while preventing it from being triggered on the color picker. If a solution for this already exists, I would be grateful for any help. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
Hey @Wolf-Den1994! Let me confirm if I understand correctly. You want to drag the item only if touched outside of the color picker circle and don't start dragging the item if pressed inside the color picker, right? I haven't figured out the right approach yet but and I think it might not be that easy because, as far as I know, gesture handler needs to be explicitly told which gesture should be blocked when another gesture is being handled, so the color picker library should be able to somehow block the gesture recognized by my library when its gesture handler detects a gesture. I cam up with a workable workaround, though, so maybe you would like to implement something similar to this: const SortableItem = memo(function SortableItem({
setValue,
value
}: SortableItemProps) {
const { gesture } = useItemContext();
return (
<View
style={{
backgroundColor: '#aaa',
paddingHorizontal: 20,
paddingVertical: 32,
width: 140
}}>
{/* Hacky workaround with the gesture detector being attached to the view in the background */}
<GestureDetector gesture={gesture}>
<View collapsable={false} style={StyleSheet.absoluteFill} />
</GestureDetector>
<ColorPicker
thumbShape='circle'
thumbSize={18}
value={value}
onChangeJS={color => setValue(color.hex)}
onCompleteJS={color => setValue(color.hex)}>
<Panel3 centerChannel='saturation' />
</ColorPicker>
</View>
);
}); Basically, instead of attaching the gesture detector to the entire item, I attach it to the component rendered below the color picker. Color picker is rendered above it, so the drag gesture from my library won't fire when the color picker is pressed. More info about useItemContext is here. You would also have to pass the customHandle prop to the Let me know if it helps in any way! |
Beta Was this translation helpful? Give feedback.
-
Hi, yes, right. Your idea is great — everything works perfectly! The key point, as you said, is to pass Also, after going through the docs about Thanks a lot for the hack! |
Beta Was this translation helpful? Give feedback.
Hey @Wolf-Den1994!
Let me confirm if I understand correctly. You want to drag the item only if touched outside of the color picker circle and don't start dragging the item if pressed inside the color picker, right?
I haven't figured out the right approach yet but and I think it might not be that easy because, as far as I know, gesture handler needs to be explicitly told which gesture should be blocked when another gesture is being handled, so the color picker library should be able to somehow block the gesture recognized by my library when its gesture handler detects a gesture.
I cam up with a workable workaround, though, so maybe you would like to implement something similar to this:
const