-
-
Notifications
You must be signed in to change notification settings - Fork 1k
[docs] Gesture detectors #3894
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
base: next
Are you sure you want to change the base?
[docs] Gesture detectors #3894
Changes from all commits
4e3e30f
7ac164d
203131e
db99336
f01bd66
5490439
ded8083
e38591c
f338fa7
11c91a7
37d7438
a93970a
d23e66b
5c0b717
f293949
34a93a5
f4847dc
87a1130
b96d788
cf3f810
944d689
d2958e0
d8eaaeb
b2a373e
d3c7893
e96349e
cd7c0d6
ca2d46a
1811c9c
4fa234f
fb8e2ef
47da2df
c8a4a76
5c3d918
a8c6ccc
421d247
b14eadf
b769862
49b1d3e
41f7a4f
1fb9b51
6d2da5a
f90b378
b4cd005
5255e4a
205c0a8
4c53b94
42b04b1
03501dc
e1fae87
59fd8df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,211 @@ | ||||||||||
| --- | ||||||||||
| id: gesture-detectors | ||||||||||
| title: Gesture Detectors | ||||||||||
| sidebar_label: Gesture detectors | ||||||||||
| sidebar_position: 3 | ||||||||||
| --- | ||||||||||
|
|
||||||||||
| ## Gesture Detector | ||||||||||
|
|
||||||||||
| `GestureDetector` is the core component of RNGH3. Unlike in previous version, it no longer manages the lifecycle of gestures directly. It supports recognizing multiple gestures through [gesture composition](/docs/fundamentals/gesture-composition). | ||||||||||
|
|
||||||||||
| To facilitate a smooth migration, the gesture property accepts both RNGH3 and RNGH2 gestures. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I'm not sold on using RNGH2 and RNGH3 as a way to differentiate between the two APIs, especially given that some parts stayed the same (i.e. GestureDetector).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How nested |
||||||||||
|
|
||||||||||
| When using RNGH3 gestures, you can also integrate them directly with the [Animated API](https://reactnative.dev/docs/animated). | ||||||||||
|
|
||||||||||
| ### Example | ||||||||||
|
|
||||||||||
| #### Simple example | ||||||||||
|
|
||||||||||
| ```js | ||||||||||
| import { GestureDetector, useTapGesture } from 'react-native-gesture-handler'; | ||||||||||
|
|
||||||||||
| export default function App() { | ||||||||||
| const tap = useTapGesture({}); | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this have a console.log at least? |
||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <GestureHandlerRootView> | ||||||||||
| // highlight-next-line | ||||||||||
| <GestureDetector gesture={tap}> | ||||||||||
| <Animated.View /> | ||||||||||
| // highlight-next-line | ||||||||||
| </GestureDetector> | ||||||||||
| </GestureHandlerRootView> | ||||||||||
| ); | ||||||||||
| } | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| #### Usage with Animated API | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might be worth its own page. |
||||||||||
|
|
||||||||||
| ```js | ||||||||||
| import * as React from 'react'; | ||||||||||
| import { Animated, useAnimatedValue } from 'react-native'; | ||||||||||
| import { | ||||||||||
| GestureHandlerRootView, | ||||||||||
| GestureDetector, | ||||||||||
| usePanGesture, | ||||||||||
| } from 'react-native-gesture-handler'; | ||||||||||
|
|
||||||||||
| export default function App() { | ||||||||||
| const value = useAnimatedValue(0); | ||||||||||
| const event = Animated.event( | ||||||||||
| [{ nativeEvent: { handlerData: { translationX: value } } }], | ||||||||||
| { | ||||||||||
| useNativeDriver: true, | ||||||||||
| } | ||||||||||
| ); | ||||||||||
|
|
||||||||||
| const gesture = usePanGesture({ | ||||||||||
| onUpdate: event, | ||||||||||
| }); | ||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <GestureHandlerRootView> | ||||||||||
| // highlight-next-line | ||||||||||
| <GestureDetector gesture={gesture}> | ||||||||||
| <Animated.View | ||||||||||
| style={[ | ||||||||||
| { | ||||||||||
| width: 150, | ||||||||||
| height: 150, | ||||||||||
| backgroundColor: '#b58df1', | ||||||||||
| }, | ||||||||||
| { transform: [{ translateX: value }] }, | ||||||||||
| ]} | ||||||||||
| /> | ||||||||||
| // highlight-next-line | ||||||||||
| </GestureDetector> | ||||||||||
| </GestureHandlerRootView> | ||||||||||
| ); | ||||||||||
| } | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| ## Virtual Detectors | ||||||||||
|
|
||||||||||
| In RNGH3, `GestureDetector` is a standalone native component. Depending on your view hierarchy, this can occasionally disrupt interactions between specific components. To resolve this, use `InterceptingGestureDetector` in combination with `VirtualNativeDetector`. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK, the established name is |
||||||||||
|
|
||||||||||
| ### InterceptingGestureDetector | ||||||||||
|
|
||||||||||
| `InterceptingGestureDetector` functions like a standard `GestureDetector`, but adds support for `VirtualGestureDetector` within its component subtree. Because it can be used solely to establish the context for virtual detectors, the [`gesture`](#gesture) property is optional. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Idk, what do you think? |
||||||||||
|
|
||||||||||
| ### VirtualGestureDetector | ||||||||||
|
|
||||||||||
| `VirtualGestureDetector` is similar to the `GestureDetector` from RNGH2. Because it is not a native component, it does not interfere with the native view hierarchy. This allows you to attach gestures without disrupting functionality that depends on that hierarchy. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think virtual detector deserves a known use case subsection: svg, nested text. People will search for it, and it will be easier for llm's to figure out if it is explicit. |
||||||||||
|
|
||||||||||
| ### Example | ||||||||||
|
|
||||||||||
| ```js | ||||||||||
| import React from 'react'; | ||||||||||
| import { View, StyleSheet } from 'react-native'; | ||||||||||
| import { | ||||||||||
| GestureHandlerRootView, | ||||||||||
| InterceptingGestureDetector, | ||||||||||
| useTapGesture, | ||||||||||
| VirtualGestureDetector, | ||||||||||
| } from 'react-native-gesture-handler'; | ||||||||||
| import Svg, { Circle } from 'react-native-svg'; | ||||||||||
|
|
||||||||||
| export default function App() { | ||||||||||
| const outerTap = useTapGesture({}); | ||||||||||
| const innerTap = useTapGesture({}); | ||||||||||
|
Comment on lines
+109
to
+110
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <GestureHandlerRootView style={styles.container}> | ||||||||||
| // highlight-next-line | ||||||||||
| <InterceptingGestureDetector gesture={innerTap}> | ||||||||||
| <View style={styles.box}> | ||||||||||
| <Svg height="250" width="250"> | ||||||||||
| // highlight-next-line | ||||||||||
| <VirtualGestureDetector gesture={outerTap}> | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The inner component's gesture should probably be |
||||||||||
| <Circle | ||||||||||
| cx="125" | ||||||||||
| cy="125" | ||||||||||
| r="125" | ||||||||||
| fill="#001A72" | ||||||||||
| onPress={() => {}} | ||||||||||
| /> | ||||||||||
| // highlight-next-line | ||||||||||
| </VirtualGestureDetector> | ||||||||||
| </Svg> | ||||||||||
| </View> | ||||||||||
| // highlight-next-line | ||||||||||
| </InterceptingGestureDetector> | ||||||||||
| </GestureHandlerRootView> | ||||||||||
| ); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| const styles = StyleSheet.create({ | ||||||||||
| container: { | ||||||||||
| flex: 1, | ||||||||||
| alignItems: 'center', | ||||||||||
| justifyContent: 'center', | ||||||||||
| }, | ||||||||||
| box: { | ||||||||||
| backgroundColor: '#b58df1', | ||||||||||
| }, | ||||||||||
| }); | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| ## Interaction with Reanimated | ||||||||||
|
|
||||||||||
| `GestureDetector` will decide whether to use [Reanimated](https://docs.swmansion.com/react-native-reanimated/) to process provided gestures based on their configuration. If any of the callbacks is a worklet and Reanimated is not explicitly turned off, tools provided by the Reanimated will be utilized bringing ability to handle gestures synchronously. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| ## Properties | ||||||||||
|
|
||||||||||
| ### gesture | ||||||||||
|
|
||||||||||
| ```ts | ||||||||||
| gesture: SingleGesture | ComposedGesture; | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| A gesture object containing the configuration and callbacks. Can be any of the base gestures or any [`ComposedGesture`](/docs/fundamentals/gesture-composition). | ||||||||||
|
|
||||||||||
| ### userSelect (Web only) | ||||||||||
|
|
||||||||||
| ```ts | ||||||||||
| userSelect: 'none' | 'auto' | 'text'; | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| This parameter allows to specify which `userSelect` property should be applied to underlying view. Default value is set to `"none"`. | ||||||||||
|
|
||||||||||
| ### touchAction (Web only) | ||||||||||
|
|
||||||||||
| ```ts | ||||||||||
| userSelect: TouchAction; | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| This parameter allows to specify which `touchAction` property should be applied to underlying view. Supports all CSS [touch-action](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/touch-action) values. Default value is set to `"none"`. | ||||||||||
|
|
||||||||||
| ### enableContextMenu (Web only) | ||||||||||
|
|
||||||||||
| ```ts | ||||||||||
| enableContextMenu: boolean; | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| Specifies whether context menu should be enabled after clicking on underlying view with right mouse button. Default value is set to `false`. | ||||||||||
|
|
||||||||||
| ## Remarks | ||||||||||
|
|
||||||||||
| - Using the same instance of a gesture across multiple Gesture Detectors is not possible. Have a look at the code below: | ||||||||||
|
|
||||||||||
| ```jsx | ||||||||||
| export default function Example() { | ||||||||||
| const pan = usePanGesture({}); | ||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <View> | ||||||||||
| // highlight-next-line | ||||||||||
| <GestureDetector gesture={pan}> | ||||||||||
| <View> | ||||||||||
| // highlight-next-line | ||||||||||
| <GestureDetector gesture={pan}> | ||||||||||
| <View /> | ||||||||||
| </GestureDetector> | ||||||||||
| </View> | ||||||||||
| </GestureDetector> | ||||||||||
| </View> | ||||||||||
| ); | ||||||||||
| } | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| This example will throw an error, becuse we try to use the same instance of `Pan` in two different Gesture Detectors. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it throw an error though? I haven't checked on ios or android but web does not throw. It attaches to only one detector, but it is undefined behaviour which one. I think at some point we discussed where to put the error check in the office, but we figured it is not trivial, as we might break reattaching. |
||||||||||
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what's the difference between the two versions?
I feel like this page should focus on what it does instead of on what it doesn't. We're going to have an entire migration guide about the differences.