-
-
Notifications
You must be signed in to change notification settings - Fork 984
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use Animated.Value as enabled prop on gesture handler #900
Comments
I was trying to achieve the same thing with the I ended up doing it like this, but it would be nice if it could be done without crossing the native bridge: const [panGestureHandlerEnabled, setPanGestureHandlerEnabled] = useState(false);
useCode(
() =>
onChange(
dragEnabled,
call([dragEnabled], ([dragEnabled]) =>
setPanGestureHandlerEnabled(!!dragEnabled)
)
),
[dragEnabled, setPanGestureHandlerEnabled]
); |
@terrysahaidak thanks for your post! This was really helpful. Dear maintainers, your lib is awesome, but the docs are complete trash. Please, take some time to improve it. I had to figure this out bit by bit through all the docs, various tutorials, and this library source code. |
@kulikalov were you able to resolve this ? |
actually wait, wrapping |
wasn't able to do what I wanted !! |
@ianmartorell this would trigger a rerender for all it's children. |
this might work
pointerEvent could possibly be an animated node and could disable / enable the this might not be enough but it's what I was looking for in this case. |
I don't think it's related. |
Hi! touch events and |
…2092) ## Description `GestureDetector` was not reattaching gestures if the underlying view has changed, which was especially noticeable when using layout animations. This PR updates `GestureDetector` to keep track of the tag of the view it's attached to and to reattach gestures it the tag changes. The second commit also fixes gestures not reattaching when manually changing the underlying view (at the expense of forcing another render), but only when Reanimated is not used. Applying the following patch: <details> <summary>Expand</summary> ```diff diff --git a/node_modules/react-native-reanimated/src/createAnimatedComponent.tsx b/node_modules/react-native-reanimated/src/createAnimatedComponent.tsx index 1cf0c3f..3f22437 100644 --- a/node_modules/react-native-reanimated/src/createAnimatedComponent.tsx +++ b/node_modules/react-native-reanimated/src/createAnimatedComponent.tsx @@ -294,19 +294,12 @@ export default function createAnimatedComponent( const node = this._getEventViewRef(); const attached = new Set(); const nextEvts = new Set(); - let viewTag: number | undefined; + let viewTag: number | undefined = RNRenderer.findHostInstance_DEPRECATED(this)._nativeTag; for (const key in this.props) { const prop = this.props[key]; if (prop instanceof AnimatedEvent) { nextEvts.add((prop as AnimatedEvent).__nodeID); - } else if ( - has('current', prop) && - prop.current instanceof WorkletEventHandler - ) { - if (viewTag === undefined) { - viewTag = prop.current.viewTag; - } } } for (const key in prevProps) { ``` </details> also makes it work when using Reanimated, but I'm not sure whether it's fine to change it this way upstream. This needs to be discussed. ## Test plan Tested on the Example app and on the following code: <details> <summary>Expand</summary> ```jsx import React, { useState } from 'react'; import { Text, View } from 'react-native'; import { FlatList, Gesture, GestureDetector, } from 'react-native-gesture-handler'; import Animated, { BounceIn } from 'react-native-reanimated'; const items = [ { name: 'Item A' }, { name: 'Item B' }, { name: 'Item C' }, { name: 'Item D' }, { name: 'Item A' }, { name: 'Item B' }, { name: 'Item C' }, { name: 'Item D' }, { name: 'Item A' }, { name: 'Item B' }, { name: 'Item C' }, { name: 'Item D' }, { name: 'Item A' }, { name: 'Item B' }, { name: 'Item C' }, { name: 'Item D' }, { name: 'Item A' }, { name: 'Item B' }, { name: 'Item C' }, { name: 'Item D' }, ]; function Item() { const [faved, setFaved] = useState(false); const color = faved ? '#900' : '#aaa'; const tap = Gesture.Tap() .onEnd(() => { setFaved(!faved); }) .runOnJS(true); return ( <GestureDetector gesture={tap}> <Animated.View key={color} entering={BounceIn} style={{ backgroundColor: color, width: 30, height: 30 }} /> </GestureDetector> ); } function renderItem({ item }: { item: { name: string } }) { return ( <View style={{ width: '100%', height: 50, backgroundColor: 'red', flexDirection: 'row', justifyContent: 'space-between', padding: 10, alignItems: 'center', }}> <Text>{item.name}</Text> <Item /> </View> ); } export default function Example() { return ( <View style={{ flex: 1 }}> <FlatList style={{ flex: 1 }} data={items} renderItem={renderItem} /> </View> ); } ``` </details> Code to test the second commit: <details> <summary>Expand</summary> ```jsx import React from 'react'; import { View } from 'react-native'; import { Gesture, GestureDetector } from 'react-native-gesture-handler'; import Animated from 'react-native-reanimated'; function Item() { console.log('render item'); return ( <Animated.View style={{ alignSelf: 'center', width: 200, height: 200, backgroundColor: 'red', }} /> ); } export default function Example() { const gesture = Gesture.Tap() .onStart(() => { console.log('a', _WORKLET); }) .runOnJS(true); console.log('render parent'); return ( <View style={{ flex: 1 }}> <GestureDetector gesture={gesture}> <Item /> </GestureDetector> </View> ); } ``` Change between `View` and `Animated.View` while the app is running and check if the tap still works. Remove `.runOnJS(true)` to test using Reanimated. </details>
There are lots of issues using PanGestureHandler with ScrollView, for example this one. Not sure it's something we can easily fix, but I think it's something we can workaround by using animated values.
Not everyone knows, you can
createAnimatedComponent
of almost every component and then use Animated.Values (for example with reanimated) to animate some of the props. That's pretty the same as usingsetNativeProps
, but instead of calling it from js, you can pass the animated value to the animated component and change it from the animation definition (in reanimated).Using this we can workaround it by disabling scroll when gesture handler should handle the touch and disable gesture handler when only scroll should handle the touch.
Not quite sure gesture handler and scroll view both concel its touches before switching it, hope so.
You can see POC using
scrollEnabled
as Animated Prop for Bottom Sheet component here (seems to be working on iOS only for now):https://snack.expo.io/@terrysahaidak/reanimated-scroll-enabled
/cc @kmagiera @osdnk
The text was updated successfully, but these errors were encountered: