software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
8.97k stars 1.3k forks source link

Possible to use animated value as gesture handle's enable prop? #849

Closed drewandre closed 4 years ago

drewandre commented 4 years ago

Description

Is a gesture handler's enabled prop only controllable on the js thread? Rather than using state to control this prop I'd like to use an animated value native-side (see below). I'm running reanimated v2 but this applied to v1 as well I imagine. As an alternative I may try using setNativeProps, but that would require lifting my refs up/forwarding the refs which would probably work but I think native side control would be ideal. Thanks!

In v2, could it also be possible to define a worklet that does this?

Code

// each component that uses a TapGestureHandler is defined an `id` prop.
// activeComponentId.value defaults to an empty string, so on mount, all gesture handlers are active.
// when one is clicked, activeComponentId.value is set to that component's id, which renders all other TapGestureHandlers as disabled

const enabled = useDerivedValue(() => {
  return activeComponentId.value === '' || activeComponentName.value === this.props.id
})

return (
  <TapGestureHandler
    enabled={enabled.value}
    ...

Package versions

React: v16.11.0 React Native: v0.62.2 React Native Reanimated: v2.0.0-alpha.1 React Native Gesture Handler: v1.6.0

jakub-gonet commented 4 years ago

Hi,

could you provide some more info for your use case? I don't really see why would you change it from the native side since it shouldn't be changing that much.

drewandre commented 4 years ago

Hi @jakub-gonet -- I solved this another way by setting zIndex on native side. I was designing a slider that behaves like iOS control center sliders. When activated, the slider's transformX and transformY move it into the center of the screen, and all other sliders' opacities fade. The issue was I could still click on an inactive, zero-opacity slider.

I ended up throwing a transparent background behind the active slider which expands to full screen with a high-level zIndex, covering all of the other sliders and preventing touch events from reaching them.

If the answer to this question is no, and you can't control the enabled prop using an animated value, I'd say this issue could be closed. Thanks.

jakub-gonet commented 4 years ago

AFAIK, not really, you should create animated TapGestureHandler by createdAnimatedComponent to use animated values in any component, as well as using addWhitelistedNativeProps or addWhitelistedUIProps to add enabled prop as settable from the native side.

To be honest it's way better to use call node and just call JS function which changes state (if rerendering at the end of the animation isn't a problem).

terrysahaidak commented 4 years ago

not sure it's gonna work since the enabled property is not used as a native prop - you cannot setNaiveProps it.

But with Reanimated2 it's not really needed anyway, IMO.

drewandre commented 4 years ago

Thanks for the advice! Hopefully this is helpful to others in the future.