Add simultaneous handlers support to make the component usable within a ScrollView (#273)

* Set react-native-gesture-handler dependency to ^1.10.0

* Ignore JetBrains IDE settings

* Add simultaneousHandlers and onGestureHandlerRef props

* Remove onGestureHandlerRef as it turned out it is not necessary

* Add simultaneousHandler prop to README
This commit is contained in:
Evrim Persembe 2021-04-03 20:45:45 +03:00 committed by GitHub
parent 0567117b2b
commit 1c0da9a29a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 41 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules/**/*
/lib
coverage/
.idea

View File

@ -31,39 +31,41 @@ yarn add react-native-draggable-flatlist
All props are spread onto underlying [FlatList](https://facebook.github.io/react-native/docs/flatlist)
| Name | Type | Description |
| :------------------------- | :---------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `T[]` | Items to be rendered. |
| `horizontal` | `boolean` | Orientation of list. |
| `renderItem` | `(params: { item: T, index: number, drag: () => void, isActive: boolean}) => JSX.Element` | Call `drag` when the row should become active (i.e. in an `onLongPress` or `onPressIn`). |
| `renderPlaceholder` | `(params: { item: T, index: number }) => React.ReactNode` | Component to be rendered underneath the hovering component |
| `keyExtractor` | `(item: T, index: number) => string` | Unique key for each item |
| `onDragBegin` | `(index: number) => void` | Called when row becomes active. |
| `onRelease` | `(index: number) => void` | Called when active row touch ends. |
| `onDragEnd` | `(params: { data: T[], from: number, to: number }) => void` | Called after animation has completed. Returns updated ordering of `data` |
| `autoscrollThreshold` | `number` | Distance from edge of container where list begins to autoscroll when dragging. |
| `autoscrollSpeed` | `number` | Determines how fast the list autoscrolls. |
| `onRef` | `(ref: React.RefObject<DraggableFlatList<T>>) => void` | Returns underlying Animated FlatList ref. |
| `animationConfig` | `Partial<Animated.SpringConfig>` | Configure list animations. See [reanimated spring config](https://github.com/software-mansion/react-native-reanimated/blob/master/react-native-reanimated.d.ts#L112-L120) |
| `activationDistance` | `number` | Distance a finger must travel before the gesture handler activates. Useful when using a draggable list within a TabNavigator so that the list does not capture navigator gestures. |
| `layoutInvalidationKey` | `string` | Changing this value forces a remeasure of all item layouts. Useful if item size/ordering updates after initial mount. |
| `onScrollOffsetChange` | `(offset: number) => void` | Called with scroll offset. Stand-in for `onScroll`. |
| `onPlaceholderIndexChange` | `(index: number) => void` | Called when the index of the placeholder changes |
| `dragItemOverflow` | `boolean` | If true, dragged item follows finger beyond list boundary. |
| `dragHitSlop` | `object: {top: number, left: number, bottom: number, right: number}` | Enables control over what part of the connected view area can be used to begin recognizing the gesture. Numbers need to be non-positive (only possible to reduce responsive area). |
| `debug` | `boolean` | Enables debug logging and animation debugger. |
| `containerStyle` | `StyleProp<ViewStyle>` | Style of the main component. |
| Name | Type | Description |
| :------------------------- | :---------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | `T[]` | Items to be rendered. |
| `horizontal` | `boolean` | Orientation of list. |
| `renderItem` | `(params: { item: T, index: number, drag: () => void, isActive: boolean}) => JSX.Element` | Call `drag` when the row should become active (i.e. in an `onLongPress` or `onPressIn`). |
| `renderPlaceholder` | `(params: { item: T, index: number }) => React.ReactNode` | Component to be rendered underneath the hovering component |
| `keyExtractor` | `(item: T, index: number) => string` | Unique key for each item |
| `onDragBegin` | `(index: number) => void` | Called when row becomes active. |
| `onRelease` | `(index: number) => void` | Called when active row touch ends. |
| `onDragEnd` | `(params: { data: T[], from: number, to: number }) => void` | Called after animation has completed. Returns updated ordering of `data` |
| `autoscrollThreshold` | `number` | Distance from edge of container where list begins to autoscroll when dragging. |
| `autoscrollSpeed` | `number` | Determines how fast the list autoscrolls. |
| `onRef` | `(ref: React.RefObject<DraggableFlatList<T>>) => void` | Returns underlying Animated FlatList ref. |
| `animationConfig` | `Partial<Animated.SpringConfig>` | Configure list animations. See [reanimated spring config](https://github.com/software-mansion/react-native-reanimated/blob/master/react-native-reanimated.d.ts#L112-L120) |
| `activationDistance` | `number` | Distance a finger must travel before the gesture handler activates. Useful when using a draggable list within a TabNavigator so that the list does not capture navigator gestures. |
| `layoutInvalidationKey` | `string` | Changing this value forces a remeasure of all item layouts. Useful if item size/ordering updates after initial mount. |
| `onScrollOffsetChange` | `(offset: number) => void` | Called with scroll offset. Stand-in for `onScroll`. |
| `onPlaceholderIndexChange` | `(index: number) => void` | Called when the index of the placeholder changes |
| `dragItemOverflow` | `boolean` | If true, dragged item follows finger beyond list boundary. |
| `dragHitSlop` | `object: {top: number, left: number, bottom: number, right: number}` | Enables control over what part of the connected view area can be used to begin recognizing the gesture. Numbers need to be non-positive (only possible to reduce responsive area). |
| `debug` | `boolean` | Enables debug logging and animation debugger. |
| `containerStyle` | `StyleProp<ViewStyle>` | Style of the main component. |
| `simultaneousHandlers` | `React.Ref<any>` or `React.Ref<any>[]` | References to other gesture handlers, mainly useful when using this component within a `ScrollView`. See [Cross handler interactions](https://docs.swmansion.com/react-native-gesture-handler/docs/interactions/). |
## Example
Example snack: https://snack.expo.io/@computerjazz/rndfl-example <br />
Example snack with scale effect on hover: https://snack.expo.io/@computerjazz/rndfl-dragwithhovereffect
```typescript
import React, { useState, useCallback } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import React, { useState, useCallback } from "react";
import { View, TouchableOpacity, Text } from "react-native";
import DraggableFlatList, {
RenderItemParams,
} from 'react-native-draggable-flatlist';
RenderItemParams
} from "react-native-draggable-flatlist";
const NUM_ITEMS = 10;
@ -78,7 +80,7 @@ const exampleData: Item[] = [...Array(20)].map((d, index) => {
return {
key: `item-${backgroundColor}`,
label: String(index),
backgroundColor,
backgroundColor
};
});
@ -97,17 +99,19 @@ function Example() {
<TouchableOpacity
style={{
height: 100,
backgroundColor: isActive ? 'red' : item.backgroundColor,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: isActive ? "red" : item.backgroundColor,
alignItems: "center",
justifyContent: "center"
}}
onLongPress={drag}>
onLongPress={drag}
>
<Text
style={{
fontWeight: 'bold',
color: 'white',
fontSize: 32,
}}>
fontWeight: "bold",
color: "white",
fontSize: 32
}}
>
{item.label}
</Text>
</TouchableOpacity>

View File

@ -58,7 +58,7 @@
"pretty-quick": "^2.0.1",
"react": "^16.13.1",
"react-native": "^0.61.5",
"react-native-gesture-handler": "^1.5.3",
"react-native-gesture-handler": "^1.10.0",
"react-native-reanimated": "^1.13.0",
"react-test-renderer": "~16.11.0",
"typescript": "^3.7.3"

View File

@ -113,6 +113,7 @@ export type DraggableFlatListProps<T> = Modify<
onPlaceholderIndexChange?: (placeholderIndex: number) => void;
containerStyle?: StyleProp<ViewStyle>;
dragItemOverflow?: boolean;
simultaneousHandlers?: React.Ref<any> | React.Ref<any>[];
} & Partial<DefaultProps>
>;
@ -1002,7 +1003,8 @@ class DraggableFlatList<T> extends React.Component<
onScrollOffsetChange,
renderPlaceholder,
onPlaceholderIndexChange,
containerStyle
containerStyle,
simultaneousHandlers
} = this.props;
const { hoverComponent } = this.state;
@ -1019,6 +1021,7 @@ class DraggableFlatList<T> extends React.Component<
hitSlop={dragHitSlop}
onGestureEvent={this.onPanGestureEvent}
onHandlerStateChange={this.onPanStateChange}
simultaneousHandlers={simultaneousHandlers}
{...dynamicProps}
>
<Animated.View
@ -1040,6 +1043,7 @@ class DraggableFlatList<T> extends React.Component<
keyExtractor={this.keyExtractor}
onScroll={this.onScroll}
scrollEventThrottle={1}
simultaneousHandlers={simultaneousHandlers}
/>
{!!hoverComponent && this.renderHoverComponent()}
<Animated.Code dependencies={[]}>

View File

@ -2331,6 +2331,13 @@ create-react-class@^15.6.3:
loose-envify "^1.3.1"
object-assign "^4.1.1"
cross-fetch@^3.0.4:
version "3.0.6"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c"
integrity sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==
dependencies:
node-fetch "2.6.1"
cross-spawn@^5.0.1, cross-spawn@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
@ -2877,6 +2884,19 @@ fbjs@^1.0.0:
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"
fbjs@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.0.tgz#0907067fb3f57a78f45d95f1eacffcacd623c165"
integrity sha512-dJd4PiDOFuhe7vk4F80Mba83Vr2QuK86FoxtgPmzBqEJahncp+13YCmfoa53KHCo6OnlXLG7eeMWPfB5CrpVKg==
dependencies:
cross-fetch "^3.0.4"
fbjs-css-vars "^1.0.0"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"
figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
@ -4848,6 +4868,11 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
node-fetch@2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
@ -5471,12 +5496,13 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339"
integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==
react-native-gesture-handler@^1.5.3:
version "1.8.0"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.8.0.tgz#18f61f51da50320f938957b0ee79bc58f47449dc"
integrity sha512-E2FZa0qZ5Bi0Z8Jg4n9DaFomHvedSjwbO2DPmUUHYRy1lH2yxXUpSrqJd6yymu+Efzmjg2+JZzsjFYA2Iq8VEQ==
react-native-gesture-handler@^1.10.0:
version "1.10.3"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.10.3.tgz#942bbf2963bbf49fa79593600ee9d7b5dab3cfc0"
integrity sha512-cBGMi1IEsIVMgoox4RvMx7V2r6bNKw0uR1Mu1o7NbuHS6BRSVLq0dP34l2ecnPlC+jpWd3le6Yg1nrdCjby2Mw==
dependencies:
"@egjs/hammerjs" "^2.0.17"
fbjs "^3.0.0"
hoist-non-react-statics "^3.3.0"
invariant "^2.2.4"
prop-types "^15.7.2"