react-native-gesture-handler 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. package/README.md +3 -2
  2. package/android/build.gradle +28 -4
  3. package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandler.kt +9 -5
  4. package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandlerOrchestrator.kt +6 -1
  5. package/android/lib/src/main/java/com/swmansion/gesturehandler/NativeViewGestureHandler.kt +103 -22
  6. package/android/lib/src/main/java/com/swmansion/gesturehandler/PanGestureHandler.kt +29 -2
  7. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +74 -84
  8. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +4 -0
  9. package/android/src/main/jni/Android.mk +1 -2
  10. package/android/src/paper/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerDelegate.java +12 -9
  11. package/android/src/paper/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerInterface.java +1 -0
  12. package/ios/Handlers/RNFlingHandler.m +43 -1
  13. package/ios/Handlers/{RNNativeViewHandler.m → RNNativeViewHandler.mm} +13 -1
  14. package/ios/Handlers/RNPanHandler.m +27 -0
  15. package/ios/RNGestureHandler.h +1 -0
  16. package/ios/RNGestureHandler.m +22 -4
  17. package/ios/RNGestureHandlerManager.mm +10 -2
  18. package/ios/RNGestureHandlerModule.mm +4 -1
  19. package/ios/RNManualActivationRecognizer.m +10 -3
  20. package/ios/RNRootViewGestureRecognizer.m +12 -1
  21. package/lib/commonjs/RNGestureHandlerModule.macos.js +81 -0
  22. package/lib/commonjs/RNGestureHandlerModule.macos.js.map +1 -0
  23. package/lib/commonjs/components/DrawerLayout.js +38 -11
  24. package/lib/commonjs/components/DrawerLayout.js.map +1 -1
  25. package/lib/commonjs/components/GestureButtons.js.map +1 -1
  26. package/lib/commonjs/components/touchables/GenericTouchable.js +4 -1
  27. package/lib/commonjs/components/touchables/GenericTouchable.js.map +1 -1
  28. package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  29. package/lib/commonjs/handlers/ForceTouchGestureHandler.js +2 -1
  30. package/lib/commonjs/handlers/ForceTouchGestureHandler.js.map +1 -1
  31. package/lib/commonjs/handlers/PanGestureHandler.js +1 -1
  32. package/lib/commonjs/handlers/PanGestureHandler.js.map +1 -1
  33. package/lib/commonjs/handlers/PressabilityDebugView.js +14 -0
  34. package/lib/commonjs/handlers/PressabilityDebugView.js.map +1 -0
  35. package/lib/commonjs/handlers/PressabilityDebugView.web.js +12 -0
  36. package/lib/commonjs/handlers/PressabilityDebugView.web.js.map +1 -0
  37. package/lib/commonjs/handlers/createHandler.js +25 -11
  38. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  39. package/lib/commonjs/handlers/gestureHandlerCommon.js.map +1 -1
  40. package/lib/commonjs/handlers/gestures/GestureDetector.js +83 -63
  41. package/lib/commonjs/handlers/gestures/GestureDetector.js.map +1 -1
  42. package/lib/commonjs/handlers/gestures/gesture.js +13 -2
  43. package/lib/commonjs/handlers/gestures/gesture.js.map +1 -1
  44. package/lib/commonjs/handlers/gestures/gestureStateManager.js +13 -9
  45. package/lib/commonjs/handlers/gestures/gestureStateManager.js.map +1 -1
  46. package/lib/commonjs/handlers/gestures/panGesture.js +5 -0
  47. package/lib/commonjs/handlers/gestures/panGesture.js.map +1 -1
  48. package/lib/commonjs/mocks.js +2 -0
  49. package/lib/commonjs/mocks.js.map +1 -1
  50. package/lib/commonjs/utils.js +6 -3
  51. package/lib/commonjs/utils.js.map +1 -1
  52. package/lib/commonjs/web/utils.js.map +1 -1
  53. package/lib/module/RNGestureHandlerModule.macos.js +57 -0
  54. package/lib/module/RNGestureHandlerModule.macos.js.map +1 -0
  55. package/lib/module/components/DrawerLayout.js +38 -11
  56. package/lib/module/components/DrawerLayout.js.map +1 -1
  57. package/lib/module/components/GestureButtons.js.map +1 -1
  58. package/lib/module/components/touchables/GenericTouchable.js +4 -1
  59. package/lib/module/components/touchables/GenericTouchable.js.map +1 -1
  60. package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  61. package/lib/module/handlers/ForceTouchGestureHandler.js +1 -1
  62. package/lib/module/handlers/ForceTouchGestureHandler.js.map +1 -1
  63. package/lib/module/handlers/PanGestureHandler.js +1 -1
  64. package/lib/module/handlers/PanGestureHandler.js.map +1 -1
  65. package/lib/module/handlers/PressabilityDebugView.js +3 -0
  66. package/lib/module/handlers/PressabilityDebugView.js.map +1 -0
  67. package/lib/module/handlers/PressabilityDebugView.web.js +5 -0
  68. package/lib/module/handlers/PressabilityDebugView.web.js.map +1 -0
  69. package/lib/module/handlers/createHandler.js +26 -12
  70. package/lib/module/handlers/createHandler.js.map +1 -1
  71. package/lib/module/handlers/gestureHandlerCommon.js.map +1 -1
  72. package/lib/module/handlers/gestures/GestureDetector.js +83 -63
  73. package/lib/module/handlers/gestures/GestureDetector.js.map +1 -1
  74. package/lib/module/handlers/gestures/gesture.js +13 -2
  75. package/lib/module/handlers/gestures/gesture.js.map +1 -1
  76. package/lib/module/handlers/gestures/gestureStateManager.js +13 -9
  77. package/lib/module/handlers/gestures/gestureStateManager.js.map +1 -1
  78. package/lib/module/handlers/gestures/panGesture.js +5 -0
  79. package/lib/module/handlers/gestures/panGesture.js.map +1 -1
  80. package/lib/module/mocks.js +2 -0
  81. package/lib/module/mocks.js.map +1 -1
  82. package/lib/module/utils.js +2 -1
  83. package/lib/module/utils.js.map +1 -1
  84. package/lib/module/web/utils.js.map +1 -1
  85. package/lib/typescript/RNGestureHandlerModule.macos.d.ts +34 -0
  86. package/lib/typescript/RNGestureHandlerModule.web.d.ts +1 -1
  87. package/lib/typescript/components/DrawerLayout.d.ts +3 -0
  88. package/lib/typescript/components/GestureButtons.d.ts +6 -0
  89. package/lib/typescript/fabric/RNGestureHandlerButtonNativeComponent.d.ts +1 -0
  90. package/lib/typescript/handlers/ForceTouchGestureHandler.d.ts +2 -2
  91. package/lib/typescript/handlers/PanGestureHandler.d.ts +2 -1
  92. package/lib/typescript/handlers/PressabilityDebugView.d.ts +1 -0
  93. package/lib/typescript/handlers/PressabilityDebugView.web.d.ts +1 -0
  94. package/lib/typescript/handlers/gestureHandlerCommon.d.ts +1 -0
  95. package/lib/typescript/handlers/gestures/GestureDetector.d.ts +2 -1
  96. package/lib/typescript/handlers/gestures/gesture.d.ts +3 -0
  97. package/lib/typescript/handlers/gestures/panGesture.d.ts +1 -0
  98. package/lib/typescript/mocks.d.ts +1 -0
  99. package/lib/typescript/web/NodeManager.d.ts +2 -2
  100. package/package.json +1 -1
  101. package/src/RNGestureHandlerModule.macos.ts +62 -0
  102. package/src/components/DrawerLayout.tsx +34 -10
  103. package/src/components/GestureButtons.tsx +7 -0
  104. package/src/components/touchables/GenericTouchable.tsx +1 -0
  105. package/src/fabric/RNGestureHandlerButtonNativeComponent.ts +1 -0
  106. package/src/handlers/ForceTouchGestureHandler.ts +3 -2
  107. package/src/handlers/PanGestureHandler.ts +2 -0
  108. package/src/handlers/PressabilityDebugView.tsx +2 -0
  109. package/src/handlers/PressabilityDebugView.web.tsx +4 -0
  110. package/src/handlers/{createHandler.ts → createHandler.tsx} +32 -17
  111. package/src/handlers/gestureHandlerCommon.ts +2 -0
  112. package/src/handlers/gestures/GestureDetector.tsx +107 -81
  113. package/src/handlers/gestures/gesture.ts +16 -0
  114. package/src/handlers/gestures/gestureStateManager.ts +13 -8
  115. package/src/handlers/gestures/panGesture.ts +5 -0
  116. package/src/mocks.ts +2 -0
  117. package/src/utils.ts +3 -1
  118. package/src/web/utils.ts +1 -1
  119. package/ios/RNGestureHandler.xcodeproj/project.xcworkspace/xcuserdata/jakubpiasecki.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  120. package/ios/RNGestureHandler.xcodeproj/xcuserdata/jakubpiasecki.xcuserdatad/xcschemes/xcschememanagement.plist +0 -19
package/README.md CHANGED
@@ -24,7 +24,7 @@ Check out our dedicated documentation page for info about this library, API refe
24
24
  If you want to play with the API but don't feel like trying it on a real app, you can run the example project. Clone the repo, go to the `example` folder and run:
25
25
 
26
26
  ```bash
27
- yarn install
27
+ yarn install
28
28
  ```
29
29
 
30
30
  If you are running on ios, run `pod install` in the ios folder
@@ -44,7 +44,8 @@ You will need to have an Android or iOS device or emulator connected as well as
44
44
  | <1.1.0 | 0.50.0+ |
45
45
 
46
46
  It may be possible to use newer versions of react-native-gesture-handler on React Native with version <= 0.59 by reverse Jetifying.
47
- Read more on that here https://github.com/mikehardy/jetifier#to-reverse-jetify--convert-node_modules-dependencies-to-support-libraries
47
+ Read more on that here <https://github.com/mikehardy/jetifier#to-reverse-jetify--convert-node_modules-dependencies-to-support-libraries>
48
+
48
49
  ## License
49
50
 
50
51
  Gesture handler library is licensed under [The MIT License](LICENSE).
@@ -1,4 +1,5 @@
1
1
  import groovy.json.JsonSlurper
2
+ import java.nio.file.Paths
2
3
 
3
4
  buildscript {
4
5
  def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['RNGH_kotlinVersion']
@@ -20,6 +21,20 @@ def isNewArchitectureEnabled() {
20
21
  return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
21
22
  }
22
23
 
24
+ def findNodeModulePath(baseDir, packageName) {
25
+ def basePath = baseDir.toPath().normalize()
26
+ // Node's module resolution algorithm searches up to the root directory,
27
+ // after which the base path will be null
28
+ while (basePath) {
29
+ def candidatePath = Paths.get(basePath.toString(), "node_modules", packageName)
30
+ if (candidatePath.toFile().exists()) {
31
+ return candidatePath.toString()
32
+ }
33
+ basePath = basePath.getParent()
34
+ }
35
+ return null
36
+ }
37
+
23
38
  if (isNewArchitectureEnabled()) {
24
39
  apply plugin: 'com.facebook.react'
25
40
  }
@@ -51,6 +66,15 @@ repositories {
51
66
  android {
52
67
  compileSdkVersion safeExtGet("compileSdkVersion", 28)
53
68
 
69
+ // Used to override the NDK path/version on internal CI or by allowing
70
+ // users to customize the NDK path/version from their root project (e.g. for M1 support)
71
+ if (rootProject.hasProperty("ndkPath")) {
72
+ ndkPath rootProject.ext.ndkPath
73
+ }
74
+ if (rootProject.hasProperty("ndkVersion")) {
75
+ ndkVersion rootProject.ext.ndkVersion
76
+ }
77
+
54
78
  defaultConfig {
55
79
  minSdkVersion safeExtGet('minSdkVersion', 16)
56
80
  targetSdkVersion safeExtGet('targetSdkVersion', 28)
@@ -66,8 +90,8 @@ android {
66
90
  "NDK_TOOLCHAIN_VERSION=clang",
67
91
  "GENERATED_SRC_DIR=${appProject.buildDir}/generated/source",
68
92
  "PROJECT_BUILD_DIR=${appProject.buildDir}",
69
- "REACT_ANDROID_DIR=${appProject.rootDir}/../node_modules/react-native/ReactAndroid",
70
- "REACT_ANDROID_BUILD_DIR=${appProject.rootDir}/../node_modules/react-native/ReactAndroid/build"
93
+ "REACT_ANDROID_DIR=${findNodeModulePath(appProject.rootDir, "react-native") ?: "../node_modules/react-native/"}/ReactAndroid",
94
+ "REACT_ANDROID_BUILD_DIR=${findNodeModulePath(appProject.rootDir, "react-native") ?: "../node_modules/react-native/"}/ReactAndroid/build"
71
95
  cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
72
96
  cppFlags "-std=c++17"
73
97
  targets "rngesturehandler_modules"
@@ -148,9 +172,9 @@ dependencies {
148
172
 
149
173
  if (isNewArchitectureEnabled()) {
150
174
  react {
151
- reactRoot = rootProject.file("../node_modules/react-native/")
175
+ reactNativeDir = rootProject.file(findNodeModulePath(rootProject.rootDir, "react-native") ?: "../node_modules/react-native/")
152
176
  jsRootDir = file("../src/fabric/")
153
- codegenDir = rootProject.file("../node_modules/react-native-codegen/")
177
+ codegenDir = rootProject.file(findNodeModulePath(rootProject.rootDir, "react-native-codegen") ?: "../node_modules/react-native-codegen/")
154
178
  libraryName = "rngesturehandler"
155
179
  codegenJavaPackageName = "com.swmansion.gesturehandler"
156
180
  }
@@ -172,8 +172,12 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
172
172
  windowOffset[0] = 0
173
173
  windowOffset[1] = 0
174
174
  }
175
+
176
+ onPrepare()
175
177
  }
176
178
 
179
+ protected open fun onPrepare() {}
180
+
177
181
  private fun getWindow(context: Context?): Window? {
178
182
  if (context == null) return null
179
183
  if (context is Activity) return context.window
@@ -253,9 +257,9 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
253
257
  }
254
258
  initPointerProps(trackedPointersIDsCount)
255
259
  var count = 0
256
- val oldX = event.x
257
- val oldY = event.y
258
- event.setLocation(event.rawX, event.rawY)
260
+ val deltaX = event.rawX - event.x
261
+ val deltaY = event.rawY - event.y
262
+ event.offsetLocation(deltaX, deltaY)
259
263
  var index = 0
260
264
  val size = event.pointerCount
261
265
  while (index < size) {
@@ -298,8 +302,8 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
298
302
  } catch (e: IllegalArgumentException) {
299
303
  throw AdaptEventException(this, event, e)
300
304
  }
301
- event.setLocation(oldX, oldY)
302
- result.setLocation(oldX, oldY)
305
+ event.offsetLocation(-deltaX, -deltaY)
306
+ result.offsetLocation(-deltaX, -deltaY)
303
307
  return result
304
308
  }
305
309
 
@@ -475,7 +475,12 @@ class GestureHandlerOrchestrator(
475
475
  PointerEventsConfig.BOX_NONE -> {
476
476
  // This view can't be the target, but its children might
477
477
  if (view is ViewGroup) {
478
- extractGestureHandlers(view, coords, pointerId)
478
+ extractGestureHandlers(view, coords, pointerId).also { found ->
479
+ // A child view is handling touch, also extract handlers attached to this view
480
+ if (found) {
481
+ recordViewHandlersForPointer(view, coords, pointerId)
482
+ }
483
+ }
479
484
  } else false
480
485
  }
481
486
  PointerEventsConfig.AUTO -> {
@@ -3,13 +3,16 @@ package com.swmansion.gesturehandler
3
3
  import android.os.SystemClock
4
4
  import android.view.MotionEvent
5
5
  import android.view.View
6
+ import android.view.ViewConfiguration
6
7
  import android.view.ViewGroup
7
- import com.swmansion.gesturehandler.react.RNGestureHandlerButtonViewManager
8
+ import com.facebook.react.views.textinput.ReactEditText
8
9
 
9
10
  class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
10
11
  private var shouldActivateOnStart = false
11
12
  private var disallowInterruption = false
12
13
 
14
+ private var hook: NativeViewGestureHandlerHook = defaultHook
15
+
13
16
  init {
14
17
  setShouldCancelWhenOutside(true)
15
18
  }
@@ -34,13 +37,17 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
34
37
  }
35
38
 
36
39
  override fun shouldRecognizeSimultaneously(handler: GestureHandler<*>): Boolean {
40
+ // if the gesture is marked by user as simultaneous with other or the hook return true
41
+ if (super.shouldRecognizeSimultaneously(handler) || hook.shouldRecognizeSimultaneously(handler)) {
42
+ return true
43
+ }
44
+
37
45
  if (handler is NativeViewGestureHandler) {
38
46
  // Special case when the peer handler is also an instance of NativeViewGestureHandler:
39
47
  // For the `disallowInterruption` to work correctly we need to check the property when
40
48
  // accessed as a peer, because simultaneous recognizers can be set on either side of the
41
49
  // connection.
42
- val nativeWrapper = handler
43
- if (nativeWrapper.state == STATE_ACTIVE && nativeWrapper.disallowInterruption) {
50
+ if (handler.state == STATE_ACTIVE && handler.disallowInterruption) {
44
51
  // other handler is active and it disallows interruption, we don't want to get into its way
45
52
  return false
46
53
  }
@@ -52,7 +59,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
52
59
  // as it means the other handler has turned active and returning `true` would prevent it from
53
60
  // interrupting the current handler
54
61
  false
55
- } else state == STATE_ACTIVE && canBeInterrupted
62
+ } else state == STATE_ACTIVE && canBeInterrupted && (!hook.shouldCancelRootViewGestureHandlerIfNecessary() || handler.tag > 0)
56
63
  // otherwise we can only return `true` if already in an active state
57
64
  }
58
65
 
@@ -60,19 +67,10 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
60
67
  return !disallowInterruption
61
68
  }
62
69
 
63
- private fun canStart(): Boolean {
64
- val view = view
65
- if (view is StateChangeHook) {
66
- return view.canStart()
67
- }
68
-
69
- return true
70
- }
71
-
72
- private fun afterGestureEnd() {
73
- val view = view
74
- if (view is StateChangeHook) {
75
- view.afterGestureEnd()
70
+ override fun onPrepare() {
71
+ when (val view = view) {
72
+ is NativeViewGestureHandlerHook -> this.hook = view
73
+ is ReactEditText -> this.hook = EditTextHook(this, view)
76
74
  }
77
75
  }
78
76
 
@@ -84,7 +82,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
84
82
  activate()
85
83
  }
86
84
  end()
87
- afterGestureEnd()
85
+ hook.afterGestureEnd(event)
88
86
  } else if (state == STATE_UNDETERMINED || state == STATE_BEGAN) {
89
87
  when {
90
88
  shouldActivateOnStart -> {
@@ -96,8 +94,11 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
96
94
  view.onTouchEvent(event)
97
95
  activate()
98
96
  }
97
+ hook.wantsToHandleEventBeforeActivation() -> {
98
+ hook.handleEventBeforeActivation(event)
99
+ }
99
100
  state != STATE_BEGAN -> {
100
- if (canStart()) {
101
+ if (hook.canBegin()) {
101
102
  begin()
102
103
  } else {
103
104
  cancel()
@@ -117,13 +118,93 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
117
118
  view!!.onTouchEvent(event)
118
119
  }
119
120
 
121
+ override fun onReset() {
122
+ this.hook = defaultHook
123
+ }
124
+
120
125
  companion object {
121
126
  private fun tryIntercept(view: View, event: MotionEvent) =
122
127
  view is ViewGroup && view.onInterceptTouchEvent(event)
128
+
129
+ private val defaultHook = object : NativeViewGestureHandlerHook {}
123
130
  }
124
131
 
125
- interface StateChangeHook {
126
- fun canStart(): Boolean
127
- fun afterGestureEnd()
132
+ interface NativeViewGestureHandlerHook {
133
+ /**
134
+ * Called when gesture is in the UNDETERMINED state, shouldActivateOnStart is set to false,
135
+ * and both tryIntercept and wantsToHandleEventBeforeActivation returned false.
136
+ *
137
+ * @return Boolean value signalling whether the handler can transition to the BEGAN state. If false
138
+ * the gesture will be cancelled.
139
+ */
140
+ fun canBegin() = true
141
+
142
+ /**
143
+ * Called after the gesture transitions to the END state.
144
+ */
145
+ fun afterGestureEnd(event: MotionEvent) = Unit
146
+
147
+ /**
148
+ * @return Boolean value signalling whether the gesture can be recognized simultaneously with
149
+ * other (handler). Returning false doesn't necessarily prevent it from happening.
150
+ */
151
+ fun shouldRecognizeSimultaneously(handler: GestureHandler<*>) = false
152
+
153
+ /**
154
+ * shouldActivateOnStart and tryIntercept have priority over this method
155
+ *
156
+ * @return Boolean value signalling if the hook wants to handle events passed to the handler
157
+ * before it activates (after that the events are passed to the underlying view).
158
+ */
159
+ fun wantsToHandleEventBeforeActivation() = false
160
+
161
+ /**
162
+ * Will be called with events if wantsToHandleEventBeforeActivation returns true.
163
+ */
164
+ fun handleEventBeforeActivation(event: MotionEvent) = Unit
165
+
166
+ /**
167
+ * @return Boolean value indicating whether the RootViewGestureHandler should be cancelled
168
+ * by this one.
169
+ */
170
+ fun shouldCancelRootViewGestureHandlerIfNecessary() = false
171
+ }
172
+
173
+ private class EditTextHook(
174
+ private val handler: NativeViewGestureHandler,
175
+ private val editText: ReactEditText
176
+ ) : NativeViewGestureHandlerHook {
177
+ private var startX = 0f
178
+ private var startY = 0f
179
+ private var touchSlopSquared: Int
180
+
181
+ init {
182
+ val vc = ViewConfiguration.get(editText.context)
183
+ touchSlopSquared = vc.scaledTouchSlop * vc.scaledTouchSlop
184
+ }
185
+
186
+ override fun afterGestureEnd(event: MotionEvent) {
187
+ if ((event.x - startX) * (event.x - startX) + (event.y - startY) * (event.y - startY) < touchSlopSquared) {
188
+ editText.requestFocusFromJS()
189
+ }
190
+ }
191
+
192
+ // recognize alongside every handler besides RootViewGestureHandler, which is a private inner class
193
+ // of RNGestureHandlerRootHelper so no explicit type checks, but its tag is always negative
194
+ // also if other handler is NativeViewGestureHandler then don't override the default implementation
195
+ override fun shouldRecognizeSimultaneously(handler: GestureHandler<*>) =
196
+ handler.tag > 0 && handler !is NativeViewGestureHandler
197
+
198
+ override fun wantsToHandleEventBeforeActivation() = true
199
+
200
+ override fun handleEventBeforeActivation(event: MotionEvent) {
201
+ handler.activate()
202
+ editText.onTouchEvent(event)
203
+
204
+ startX = event.x
205
+ startY = event.y
206
+ }
207
+
208
+ override fun shouldCancelRootViewGestureHandlerIfNecessary() = true
128
209
  }
129
210
  }
@@ -1,6 +1,7 @@
1
1
  package com.swmansion.gesturehandler
2
2
 
3
3
  import android.content.Context
4
+ import android.os.Handler
4
5
  import android.view.MotionEvent
5
6
  import android.view.VelocityTracker
6
7
  import android.view.ViewConfiguration
@@ -40,6 +41,9 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
40
41
  private var lastY = 0f
41
42
  private var velocityTracker: VelocityTracker? = null
42
43
  private var averageTouches = false
44
+ private var activateAfterLongPress = DEFAULT_ACTIVATE_AFTER_LONG_PRESS
45
+ private val activateDelayed = Runnable { activate() }
46
+ private var handler: Handler? = null
43
47
 
44
48
  /**
45
49
  * On Android when there are multiple pointers on the screen pan gestures most often just consider
@@ -54,7 +58,7 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
54
58
  * position of all the fingers will remain still while doing a rotation gesture.
55
59
  */
56
60
  init {
57
- val vc = ViewConfiguration.get(context)
61
+ val vc = ViewConfiguration.get(context!!)
58
62
  val touchSlop = vc.scaledTouchSlop
59
63
  defaultMinDistSq = (touchSlop * touchSlop).toFloat()
60
64
  minDistSq = defaultMinDistSq
@@ -76,6 +80,7 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
76
80
  minDistSq = defaultMinDistSq
77
81
  minPointers = DEFAULT_MIN_POINTERS
78
82
  maxPointers = DEFAULT_MAX_POINTERS
83
+ activateAfterLongPress = DEFAULT_ACTIVATE_AFTER_LONG_PRESS
79
84
  averageTouches = false
80
85
  }
81
86
 
@@ -127,6 +132,10 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
127
132
  this.averageTouches = averageTouches
128
133
  }
129
134
 
135
+ fun setActivateAfterLongPress(time: Long) = apply {
136
+ this.activateAfterLongPress = time
137
+ }
138
+
130
139
  /**
131
140
  * @param minVelocity in pixels per second
132
141
  */
@@ -177,13 +186,18 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
177
186
 
178
187
  private fun shouldFail(): Boolean {
179
188
  val dx = lastX - startX + offsetX
189
+ val dy = lastY - startY + offsetY
190
+
191
+ if (activateAfterLongPress > 0 && dx * dx + dy * dy > defaultMinDistSq) {
192
+ handler?.removeCallbacksAndMessages(null)
193
+ return true
194
+ }
180
195
  if (failOffsetXStart != MAX_VALUE_IGNORE && dx < failOffsetXStart) {
181
196
  return true
182
197
  }
183
198
  if (failOffsetXEnd != MIN_VALUE_IGNORE && dx > failOffsetXEnd) {
184
199
  return true
185
200
  }
186
- val dy = lastY - startY + offsetY
187
201
  if (failOffsetYStart != MAX_VALUE_IGNORE && dy < failOffsetYStart) {
188
202
  return true
189
203
  }
@@ -216,6 +230,13 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
216
230
  velocityTracker = VelocityTracker.obtain()
217
231
  addVelocityMovement(velocityTracker, event)
218
232
  begin()
233
+
234
+ if (activateAfterLongPress > 0) {
235
+ if (handler == null) {
236
+ handler = Handler()
237
+ }
238
+ handler!!.postDelayed(activateDelayed, activateAfterLongPress)
239
+ }
219
240
  } else if (velocityTracker != null) {
220
241
  addVelocityMovement(velocityTracker, event)
221
242
  velocityTracker!!.computeCurrentVelocity(1000)
@@ -257,7 +278,12 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
257
278
  super.activate(force)
258
279
  }
259
280
 
281
+ override fun onCancel() {
282
+ handler?.removeCallbacksAndMessages(null)
283
+ }
284
+
260
285
  override fun onReset() {
286
+ handler?.removeCallbacksAndMessages(null)
261
287
  velocityTracker?.let {
262
288
  it.recycle()
263
289
  velocityTracker = null
@@ -274,6 +300,7 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
274
300
  private const val MAX_VALUE_IGNORE = Float.MIN_VALUE
275
301
  private const val DEFAULT_MIN_POINTERS = 1
276
302
  private const val DEFAULT_MAX_POINTERS = 10
303
+ private const val DEFAULT_ACTIVATE_AFTER_LONG_PRESS = 0L
277
304
 
278
305
  /**
279
306
  * This method adds movement to {@class VelocityTracker} first resetting offset of the event so