react-native-gesture-handler 2.6.2 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +0 -8
- package/android/gradle.properties +1 -1
- package/android/lib/src/main/java/com/swmansion/gesturehandler/FlingGestureHandler.kt +7 -7
- package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandler.kt +46 -26
- package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandlerOrchestrator.kt +76 -29
- package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureUtils.kt +4 -6
- package/android/lib/src/main/java/com/swmansion/gesturehandler/LongPressGestureHandler.kt +6 -6
- package/android/lib/src/main/java/com/swmansion/gesturehandler/ManualGestureHandler.kt +1 -1
- package/android/lib/src/main/java/com/swmansion/gesturehandler/NativeViewGestureHandler.kt +1 -1
- package/android/lib/src/main/java/com/swmansion/gesturehandler/PanGestureHandler.kt +11 -11
- package/android/lib/src/main/java/com/swmansion/gesturehandler/PinchGestureHandler.kt +17 -9
- package/android/lib/src/main/java/com/swmansion/gesturehandler/RotationGestureHandler.kt +15 -8
- package/android/lib/src/main/java/com/swmansion/gesturehandler/TapGestureHandler.kt +10 -10
- package/android/noreanimated/src/main/java/com/swmansion/gesturehandler/ReanimatedEventDispatcher.kt +1 -1
- package/android/reanimated/src/main/java/com/swmansion/gesturehandler/ReanimatedEventDispatcher.kt +1 -1
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +31 -12
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +2 -2
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt +1 -1
- package/ios/RNGestureHandlerButtonComponentView.mm +4 -4
- package/lib/commonjs/web/handlers/GestureHandler.js +1 -1
- package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
- package/lib/commonjs/web/tools/PointerTracker.js +2 -2
- package/lib/commonjs/web/tools/PointerTracker.js.map +1 -1
- package/lib/module/web/handlers/GestureHandler.js +1 -1
- package/lib/module/web/handlers/GestureHandler.js.map +1 -1
- package/lib/module/web/tools/PointerTracker.js +2 -2
- package/lib/module/web/tools/PointerTracker.js.map +1 -1
- package/package.json +4 -8
- package/src/web/handlers/GestureHandler.ts +1 -0
- package/src/web/tools/PointerTracker.ts +2 -2
package/android/build.gradle
CHANGED
@@ -212,14 +212,6 @@ dependencies {
|
|
212
212
|
}
|
213
213
|
|
214
214
|
if (isNewArchitectureEnabled()) {
|
215
|
-
react {
|
216
|
-
reactNativeDir = rootProject.file(findNodeModulePath(rootProject.rootDir, "react-native") ?: "../node_modules/react-native/")
|
217
|
-
jsRootDir = file("../src/fabric/")
|
218
|
-
codegenDir = rootProject.file(findNodeModulePath(rootProject.rootDir, "react-native-codegen") ?: "../node_modules/react-native-codegen/")
|
219
|
-
libraryName = "rngesturehandler"
|
220
|
-
codegenJavaPackageName = "com.swmansion.gesturehandler"
|
221
|
-
}
|
222
|
-
|
223
215
|
// Resolves "LOCAL_SRC_FILES points to a missing file, Check that libfb.so exists or that its path is correct".
|
224
216
|
tasks.whenTaskAdded { task ->
|
225
217
|
if (task.name.contains("configureCMakeDebug")) {
|
@@ -16,4 +16,4 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryErro
|
|
16
16
|
# This option should only be used with decoupled projects. More details, visit
|
17
17
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
18
18
|
# org.gradle.parallel=true
|
19
|
-
RNGH_kotlinVersion=1.
|
19
|
+
RNGH_kotlinVersion=1.6.21
|
@@ -63,19 +63,19 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
|
|
63
63
|
}
|
64
64
|
}
|
65
65
|
|
66
|
-
override fun onHandle(event: MotionEvent) {
|
66
|
+
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
|
67
67
|
val state = state
|
68
68
|
if (state == STATE_UNDETERMINED) {
|
69
|
-
startFling(
|
69
|
+
startFling(sourceEvent)
|
70
70
|
}
|
71
71
|
if (state == STATE_BEGAN) {
|
72
|
-
tryEndFling(
|
73
|
-
if (
|
74
|
-
maxNumberOfPointersSimultaneously =
|
72
|
+
tryEndFling(sourceEvent)
|
73
|
+
if (sourceEvent.pointerCount > maxNumberOfPointersSimultaneously) {
|
74
|
+
maxNumberOfPointersSimultaneously = sourceEvent.pointerCount
|
75
75
|
}
|
76
|
-
val action =
|
76
|
+
val action = sourceEvent.actionMasked
|
77
77
|
if (action == MotionEvent.ACTION_UP) {
|
78
|
-
endFling(
|
78
|
+
endFling(sourceEvent)
|
79
79
|
}
|
80
80
|
}
|
81
81
|
}
|
@@ -3,6 +3,7 @@ package com.swmansion.gesturehandler
|
|
3
3
|
import android.app.Activity
|
4
4
|
import android.content.Context
|
5
5
|
import android.content.ContextWrapper
|
6
|
+
import android.graphics.PointF
|
6
7
|
import android.graphics.Rect
|
7
8
|
import android.view.MotionEvent
|
8
9
|
import android.view.MotionEvent.PointerCoords
|
@@ -325,7 +326,7 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
|
|
325
326
|
while handling event: $event
|
326
327
|
""".trimIndent(), e) {}
|
327
328
|
|
328
|
-
fun handle(
|
329
|
+
fun handle(transformedEvent: MotionEvent, sourceEvent: MotionEvent) {
|
329
330
|
if (!isEnabled
|
330
331
|
|| state == STATE_CANCELLED
|
331
332
|
|| state == STATE_FAILED
|
@@ -335,20 +336,20 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
|
|
335
336
|
}
|
336
337
|
|
337
338
|
// a workaround for https://github.com/software-mansion/react-native-gesture-handler/issues/1188
|
338
|
-
val
|
339
|
-
adaptEvent(
|
339
|
+
val (adaptedTransformedEvent, adaptedSourceEvent) = if (BuildConfig.DEBUG) {
|
340
|
+
arrayOf(adaptEvent(transformedEvent), adaptEvent(sourceEvent))
|
340
341
|
} else {
|
341
342
|
try {
|
342
|
-
adaptEvent(
|
343
|
+
arrayOf(adaptEvent(transformedEvent), adaptEvent(sourceEvent))
|
343
344
|
} catch (e: AdaptEventException) {
|
344
345
|
fail()
|
345
346
|
return
|
346
347
|
}
|
347
348
|
}
|
348
349
|
|
349
|
-
x =
|
350
|
-
y =
|
351
|
-
numberOfPointers =
|
350
|
+
x = adaptedTransformedEvent.x
|
351
|
+
y = adaptedTransformedEvent.y
|
352
|
+
numberOfPointers = adaptedTransformedEvent.pointerCount
|
352
353
|
isWithinBounds = isWithinBounds(view, x, y)
|
353
354
|
if (shouldCancelWhenOutside && !isWithinBounds) {
|
354
355
|
if (state == STATE_ACTIVE) {
|
@@ -358,13 +359,16 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
|
|
358
359
|
}
|
359
360
|
return
|
360
361
|
}
|
361
|
-
lastAbsolutePositionX = GestureUtils.getLastPointerX(
|
362
|
-
lastAbsolutePositionY = GestureUtils.getLastPointerY(
|
363
|
-
lastEventOffsetX =
|
364
|
-
lastEventOffsetY =
|
365
|
-
onHandle(
|
366
|
-
if (
|
367
|
-
|
362
|
+
lastAbsolutePositionX = GestureUtils.getLastPointerX(adaptedTransformedEvent, true)
|
363
|
+
lastAbsolutePositionY = GestureUtils.getLastPointerY(adaptedTransformedEvent, true)
|
364
|
+
lastEventOffsetX = adaptedTransformedEvent.rawX - adaptedTransformedEvent.x
|
365
|
+
lastEventOffsetY = adaptedTransformedEvent.rawY - adaptedTransformedEvent.y
|
366
|
+
onHandle(adaptedTransformedEvent, adaptedSourceEvent)
|
367
|
+
if (adaptedTransformedEvent != transformedEvent) {
|
368
|
+
adaptedTransformedEvent.recycle()
|
369
|
+
}
|
370
|
+
if (adaptedSourceEvent != sourceEvent) {
|
371
|
+
adaptedSourceEvent.recycle()
|
368
372
|
}
|
369
373
|
}
|
370
374
|
|
@@ -585,11 +589,11 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
|
|
585
589
|
var top = 0f
|
586
590
|
var right = view!!.width.toFloat()
|
587
591
|
var bottom = view.height.toFloat()
|
588
|
-
|
589
|
-
val padLeft = hitSlop
|
590
|
-
val padTop = hitSlop
|
591
|
-
val padRight = hitSlop
|
592
|
-
val padBottom = hitSlop
|
592
|
+
hitSlop?.let { hitSlop ->
|
593
|
+
val padLeft = hitSlop[HIT_SLOP_LEFT_IDX]
|
594
|
+
val padTop = hitSlop[HIT_SLOP_TOP_IDX]
|
595
|
+
val padRight = hitSlop[HIT_SLOP_RIGHT_IDX]
|
596
|
+
val padBottom = hitSlop[HIT_SLOP_BOTTOM_IDX]
|
593
597
|
if (hitSlopSet(padLeft)) {
|
594
598
|
left -= padLeft
|
595
599
|
}
|
@@ -602,8 +606,8 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
|
|
602
606
|
if (hitSlopSet(padBottom)) {
|
603
607
|
bottom += padBottom
|
604
608
|
}
|
605
|
-
val width = hitSlop
|
606
|
-
val height = hitSlop
|
609
|
+
val width = hitSlop[HIT_SLOP_WIDTH_IDX]
|
610
|
+
val height = hitSlop[HIT_SLOP_HEIGHT_IDX]
|
607
611
|
if (hitSlopSet(width)) {
|
608
612
|
if (!hitSlopSet(padLeft)) {
|
609
613
|
left = right - width
|
@@ -659,13 +663,29 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
|
|
659
663
|
// if the handler is waiting for failure of other one)
|
660
664
|
open fun resetProgress() {}
|
661
665
|
|
662
|
-
protected open fun onHandle(event: MotionEvent) {
|
666
|
+
protected open fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
|
663
667
|
moveToState(STATE_FAILED)
|
664
668
|
}
|
665
669
|
|
666
670
|
protected open fun onStateChange(newState: Int, previousState: Int) {}
|
667
671
|
protected open fun onReset() {}
|
668
672
|
protected open fun onCancel() {}
|
673
|
+
|
674
|
+
/**
|
675
|
+
* Transforms a point in the coordinate space of the wrapperView (GestureHandlerRootView) to
|
676
|
+
* coordinate space of the view the gesture is attached to.
|
677
|
+
*
|
678
|
+
* If the gesture handler is not currently attached to a view, it will return (NaN, NaN).
|
679
|
+
*
|
680
|
+
* This method modifies and transforms the received point.
|
681
|
+
*/
|
682
|
+
protected fun transformPoint(point: PointF): PointF {
|
683
|
+
return orchestrator?.transformPointToViewCoords(this.view, point) ?: run {
|
684
|
+
point.x = Float.NaN
|
685
|
+
point.y = Float.NaN
|
686
|
+
point
|
687
|
+
}
|
688
|
+
}
|
669
689
|
fun reset() {
|
670
690
|
view = null
|
671
691
|
orchestrator = null
|
@@ -689,14 +709,14 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
|
|
689
709
|
}
|
690
710
|
|
691
711
|
val lastRelativePositionX: Float
|
692
|
-
get() = lastAbsolutePositionX
|
712
|
+
get() = lastAbsolutePositionX
|
693
713
|
val lastRelativePositionY: Float
|
694
|
-
get() = lastAbsolutePositionY
|
714
|
+
get() = lastAbsolutePositionY
|
695
715
|
|
696
716
|
val lastPositionInWindowX: Float
|
697
|
-
get() = lastAbsolutePositionX - windowOffset[0]
|
717
|
+
get() = lastAbsolutePositionX + lastEventOffsetX - windowOffset[0]
|
698
718
|
val lastPositionInWindowY: Float
|
699
|
-
get() = lastAbsolutePositionY - windowOffset[1]
|
719
|
+
get() = lastAbsolutePositionY + lastEventOffsetY - windowOffset[1]
|
700
720
|
|
701
721
|
companion object {
|
702
722
|
const val STATE_UNDETERMINED = 0
|
package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandlerOrchestrator.kt
CHANGED
@@ -242,7 +242,7 @@ class GestureHandlerOrchestrator(
|
|
242
242
|
}
|
243
243
|
}
|
244
244
|
|
245
|
-
private fun deliverEventToGestureHandler(handler: GestureHandler<*>,
|
245
|
+
private fun deliverEventToGestureHandler(handler: GestureHandler<*>, sourceEvent: MotionEvent) {
|
246
246
|
if (!isViewAttachedUnderWrapper(handler.view)) {
|
247
247
|
handler.cancel()
|
248
248
|
return
|
@@ -250,18 +250,9 @@ class GestureHandlerOrchestrator(
|
|
250
250
|
if (!handler.wantEvents()) {
|
251
251
|
return
|
252
252
|
}
|
253
|
-
|
254
|
-
val
|
255
|
-
|
256
|
-
val oldX = event.x
|
257
|
-
val oldY = event.y
|
258
|
-
// TODO: we may consider scaling events if necessary using MotionEvent.transform
|
259
|
-
// for now the events are only offset to the top left corner of the view but if
|
260
|
-
// view or any ot the parents is scaled the other pointers position will not reflect
|
261
|
-
// their actual place in the view. On the other hand not scaling seems like a better
|
262
|
-
// approach when we want to use pointer coordinates to calculate velocity or distance
|
263
|
-
// for pinch so I don't know yet if we should transform or not...
|
264
|
-
event.setLocation(coords[0], coords[1])
|
253
|
+
|
254
|
+
val action = sourceEvent.actionMasked
|
255
|
+
val event = transformEventToViewCoords(handler.view, MotionEvent.obtain(sourceEvent))
|
265
256
|
|
266
257
|
// Touch events are sent before the handler itself has a chance to process them,
|
267
258
|
// mainly because `onTouchesUp` shoul be send befor gesture finishes. This means that
|
@@ -277,7 +268,7 @@ class GestureHandlerOrchestrator(
|
|
277
268
|
|
278
269
|
if (!handler.isAwaiting || action != MotionEvent.ACTION_MOVE) {
|
279
270
|
val isFirstEvent = handler.state == 0
|
280
|
-
handler.handle(event)
|
271
|
+
handler.handle(event, sourceEvent)
|
281
272
|
if (handler.isActive) {
|
282
273
|
// After handler is done waiting for other one to fail its progress should be
|
283
274
|
// reset, otherwise there may be a visible jump in values sent by the handler.
|
@@ -305,7 +296,7 @@ class GestureHandlerOrchestrator(
|
|
305
296
|
}
|
306
297
|
}
|
307
298
|
|
308
|
-
event.
|
299
|
+
event.recycle()
|
309
300
|
}
|
310
301
|
|
311
302
|
/**
|
@@ -329,19 +320,75 @@ class GestureHandlerOrchestrator(
|
|
329
320
|
return parent === wrapperView
|
330
321
|
}
|
331
322
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
323
|
+
/**
|
324
|
+
* Transforms an event in the coordinates of wrapperView into the coordinate space of the received view.
|
325
|
+
*
|
326
|
+
* This modifies and returns the same event as it receives
|
327
|
+
*
|
328
|
+
* @param view - view to which coordinate space the event should be transformed
|
329
|
+
* @param event - event to transform
|
330
|
+
*/
|
331
|
+
fun transformEventToViewCoords(view: View?, event: MotionEvent): MotionEvent {
|
332
|
+
if (view == null) {
|
333
|
+
return event
|
337
334
|
}
|
338
|
-
|
339
|
-
val parent = view.parent as ViewGroup
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
335
|
+
|
336
|
+
val parent = view.parent as? ViewGroup
|
337
|
+
// Events are passed down to the orchestrator by the wrapperView, so they are already in the
|
338
|
+
// relevant coordinate space. We want to stop traversing the tree when we reach it.
|
339
|
+
if (parent != wrapperView) {
|
340
|
+
transformEventToViewCoords(parent, event)
|
341
|
+
}
|
342
|
+
|
343
|
+
if (parent != null) {
|
344
|
+
val localX = event.x + parent.scrollX - view.left
|
345
|
+
val localY = event.y + parent.scrollY - view.top
|
346
|
+
event.setLocation(localX, localY)
|
347
|
+
}
|
348
|
+
|
349
|
+
if (!view.matrix.isIdentity) {
|
350
|
+
view.matrix.invert(inverseMatrix)
|
351
|
+
event.transform(inverseMatrix)
|
352
|
+
}
|
353
|
+
|
354
|
+
return event
|
355
|
+
}
|
356
|
+
|
357
|
+
/**
|
358
|
+
* Transforms a point in the coordinates of wrapperView into the coordinate space of the received view.
|
359
|
+
*
|
360
|
+
* This modifies and returns the same point as it receives
|
361
|
+
*
|
362
|
+
* @param view - view to which coordinate space the point should be transformed
|
363
|
+
* @param point - point to transform
|
364
|
+
*/
|
365
|
+
fun transformPointToViewCoords(view: View?, point: PointF): PointF {
|
366
|
+
if (view == null) {
|
367
|
+
return point
|
368
|
+
}
|
369
|
+
|
370
|
+
val parent = view.parent as? ViewGroup
|
371
|
+
// Events are passed down to the orchestrator by the wrapperView, so they are already in the
|
372
|
+
// relevant coordinate space. We want to stop traversing the tree when we reach it.
|
373
|
+
if (parent != wrapperView) {
|
374
|
+
transformPointToViewCoords(parent, point)
|
375
|
+
}
|
376
|
+
|
377
|
+
if (parent != null) {
|
378
|
+
point.x += parent.scrollX - view.left
|
379
|
+
point.y += parent.scrollY - view.top
|
380
|
+
}
|
381
|
+
|
382
|
+
if (!view.matrix.isIdentity) {
|
383
|
+
view.matrix.invert(inverseMatrix)
|
384
|
+
tempCoords[0] = point.x
|
385
|
+
tempCoords[1] = point.y
|
386
|
+
inverseMatrix.mapPoints(tempCoords)
|
387
|
+
point.x = tempCoords[0]
|
388
|
+
point.y = tempCoords[1]
|
389
|
+
}
|
390
|
+
|
391
|
+
return point
|
345
392
|
}
|
346
393
|
|
347
394
|
private fun addAwaitingHandler(handler: GestureHandler<*>) {
|
@@ -451,7 +498,7 @@ class GestureHandlerOrchestrator(
|
|
451
498
|
val child = viewConfigHelper.getChildInDrawingOrderAtIndex(viewGroup, i)
|
452
499
|
if (canReceiveEvents(child)) {
|
453
500
|
val childPoint = tempPoint
|
454
|
-
|
501
|
+
transformPointToChildViewCoords(coords[0], coords[1], viewGroup, child, childPoint)
|
455
502
|
val restoreX = coords[0]
|
456
503
|
val restoreY = coords[1]
|
457
504
|
coords[0] = childPoint.x
|
@@ -564,7 +611,7 @@ class GestureHandlerOrchestrator(
|
|
564
611
|
return isLeafOrTransparent && isTransformedTouchPointInView(coords[0], coords[1], view)
|
565
612
|
}
|
566
613
|
|
567
|
-
private fun
|
614
|
+
private fun transformPointToChildViewCoords(
|
568
615
|
x: Float,
|
569
616
|
y: Float,
|
570
617
|
parent: ViewGroup,
|
@@ -4,14 +4,13 @@ import android.view.MotionEvent
|
|
4
4
|
|
5
5
|
object GestureUtils {
|
6
6
|
fun getLastPointerX(event: MotionEvent, averageTouches: Boolean): Float {
|
7
|
-
val offset = event.rawX - event.x
|
8
7
|
val excludeIndex = if (event.actionMasked == MotionEvent.ACTION_POINTER_UP) event.actionIndex else -1
|
9
8
|
return if (averageTouches) {
|
10
9
|
var sum = 0f
|
11
10
|
var count = 0
|
12
11
|
for (i in 0 until event.pointerCount) {
|
13
12
|
if (i != excludeIndex) {
|
14
|
-
sum += event.getX(i)
|
13
|
+
sum += event.getX(i)
|
15
14
|
count++
|
16
15
|
}
|
17
16
|
}
|
@@ -21,19 +20,18 @@ object GestureUtils {
|
|
21
20
|
if (lastPointerIdx == excludeIndex) {
|
22
21
|
lastPointerIdx--
|
23
22
|
}
|
24
|
-
event.getX(lastPointerIdx)
|
23
|
+
event.getX(lastPointerIdx)
|
25
24
|
}
|
26
25
|
}
|
27
26
|
|
28
27
|
fun getLastPointerY(event: MotionEvent, averageTouches: Boolean): Float {
|
29
|
-
val offset = event.rawY - event.y
|
30
28
|
val excludeIndex = if (event.actionMasked == MotionEvent.ACTION_POINTER_UP) event.actionIndex else -1
|
31
29
|
return if (averageTouches) {
|
32
30
|
var sum = 0f
|
33
31
|
var count = 0
|
34
32
|
for (i in 0 until event.pointerCount) {
|
35
33
|
if (i != excludeIndex) {
|
36
|
-
sum += event.getY(i)
|
34
|
+
sum += event.getY(i)
|
37
35
|
count++
|
38
36
|
}
|
39
37
|
}
|
@@ -43,7 +41,7 @@ object GestureUtils {
|
|
43
41
|
if (lastPointerIdx == excludeIndex) {
|
44
42
|
lastPointerIdx -= 1
|
45
43
|
}
|
46
|
-
event.getY(lastPointerIdx)
|
44
|
+
event.getY(lastPointerIdx)
|
47
45
|
}
|
48
46
|
}
|
49
47
|
}
|
@@ -37,13 +37,13 @@ class LongPressGestureHandler(context: Context) : GestureHandler<LongPressGestur
|
|
37
37
|
return this
|
38
38
|
}
|
39
39
|
|
40
|
-
override fun onHandle(event: MotionEvent) {
|
40
|
+
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
|
41
41
|
if (state == STATE_UNDETERMINED) {
|
42
42
|
previousTime = SystemClock.uptimeMillis()
|
43
43
|
startTime = previousTime
|
44
44
|
begin()
|
45
|
-
startX =
|
46
|
-
startY =
|
45
|
+
startX = sourceEvent.rawX
|
46
|
+
startY = sourceEvent.rawY
|
47
47
|
handler = Handler(Looper.getMainLooper())
|
48
48
|
if (minDurationMs > 0) {
|
49
49
|
handler!!.postDelayed({ activate() }, minDurationMs)
|
@@ -51,7 +51,7 @@ class LongPressGestureHandler(context: Context) : GestureHandler<LongPressGestur
|
|
51
51
|
activate()
|
52
52
|
}
|
53
53
|
}
|
54
|
-
if (
|
54
|
+
if (sourceEvent.actionMasked == MotionEvent.ACTION_UP) {
|
55
55
|
handler?.let {
|
56
56
|
it.removeCallbacksAndMessages(null)
|
57
57
|
handler = null
|
@@ -63,8 +63,8 @@ class LongPressGestureHandler(context: Context) : GestureHandler<LongPressGestur
|
|
63
63
|
}
|
64
64
|
} else {
|
65
65
|
// calculate distance from start
|
66
|
-
val deltaX =
|
67
|
-
val deltaY =
|
66
|
+
val deltaX = sourceEvent.rawX - startX
|
67
|
+
val deltaY = sourceEvent.rawY - startY
|
68
68
|
val distSq = deltaX * deltaX + deltaY * deltaY
|
69
69
|
if (distSq > maxDistSq) {
|
70
70
|
if (state == STATE_ACTIVE) {
|
@@ -3,7 +3,7 @@ package com.swmansion.gesturehandler
|
|
3
3
|
import android.view.MotionEvent
|
4
4
|
|
5
5
|
class ManualGestureHandler : GestureHandler<ManualGestureHandler>() {
|
6
|
-
override fun onHandle(event: MotionEvent) {
|
6
|
+
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
|
7
7
|
if (state == STATE_UNDETERMINED) {
|
8
8
|
begin()
|
9
9
|
}
|
@@ -75,7 +75,7 @@ class NativeViewGestureHandler : GestureHandler<NativeViewGestureHandler>() {
|
|
75
75
|
}
|
76
76
|
}
|
77
77
|
|
78
|
-
override fun onHandle(event: MotionEvent) {
|
78
|
+
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
|
79
79
|
val view = view!!
|
80
80
|
if (event.actionMasked == MotionEvent.ACTION_UP) {
|
81
81
|
view.onTouchEvent(event)
|
@@ -205,31 +205,31 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
|
|
205
205
|
return failOffsetYEnd != MIN_VALUE_IGNORE && dy > failOffsetYEnd
|
206
206
|
}
|
207
207
|
|
208
|
-
override fun onHandle(event: MotionEvent) {
|
208
|
+
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
|
209
209
|
val state = state
|
210
|
-
val action =
|
210
|
+
val action = sourceEvent.actionMasked
|
211
211
|
if (action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN) {
|
212
212
|
// update offset if new pointer gets added or removed
|
213
213
|
offsetX += lastX - startX
|
214
214
|
offsetY += lastY - startY
|
215
215
|
|
216
216
|
// reset starting point
|
217
|
-
lastX = getLastPointerX(
|
218
|
-
lastY = getLastPointerY(
|
217
|
+
lastX = getLastPointerX(sourceEvent, averageTouches)
|
218
|
+
lastY = getLastPointerY(sourceEvent, averageTouches)
|
219
219
|
startX = lastX
|
220
220
|
startY = lastY
|
221
221
|
} else {
|
222
|
-
lastX = getLastPointerX(
|
223
|
-
lastY = getLastPointerY(
|
222
|
+
lastX = getLastPointerX(sourceEvent, averageTouches)
|
223
|
+
lastY = getLastPointerY(sourceEvent, averageTouches)
|
224
224
|
}
|
225
|
-
if (state == STATE_UNDETERMINED &&
|
225
|
+
if (state == STATE_UNDETERMINED && sourceEvent.pointerCount >= minPointers) {
|
226
226
|
resetProgress()
|
227
227
|
offsetX = 0f
|
228
228
|
offsetY = 0f
|
229
229
|
velocityX = 0f
|
230
230
|
velocityY = 0f
|
231
231
|
velocityTracker = VelocityTracker.obtain()
|
232
|
-
addVelocityMovement(velocityTracker,
|
232
|
+
addVelocityMovement(velocityTracker, sourceEvent)
|
233
233
|
begin()
|
234
234
|
|
235
235
|
if (activateAfterLongPress > 0) {
|
@@ -239,7 +239,7 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
|
|
239
239
|
handler!!.postDelayed(activateDelayed, activateAfterLongPress)
|
240
240
|
}
|
241
241
|
} else if (velocityTracker != null) {
|
242
|
-
addVelocityMovement(velocityTracker,
|
242
|
+
addVelocityMovement(velocityTracker, sourceEvent)
|
243
243
|
velocityTracker!!.computeCurrentVelocity(1000)
|
244
244
|
velocityX = velocityTracker!!.xVelocity
|
245
245
|
velocityY = velocityTracker!!.yVelocity
|
@@ -250,14 +250,14 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
|
|
250
250
|
} else {
|
251
251
|
fail()
|
252
252
|
}
|
253
|
-
} else if (action == MotionEvent.ACTION_POINTER_DOWN &&
|
253
|
+
} else if (action == MotionEvent.ACTION_POINTER_DOWN && sourceEvent.pointerCount > maxPointers) {
|
254
254
|
// When new finger is placed down (POINTER_DOWN) we check if MAX_POINTERS is not exceeded
|
255
255
|
if (state == STATE_ACTIVE) {
|
256
256
|
cancel()
|
257
257
|
} else {
|
258
258
|
fail()
|
259
259
|
}
|
260
|
-
} else if (action == MotionEvent.ACTION_POINTER_UP && state == STATE_ACTIVE &&
|
260
|
+
} else if (action == MotionEvent.ACTION_POINTER_UP && state == STATE_ACTIVE && sourceEvent.pointerCount < minPointers) {
|
261
261
|
// When finger is lifted up (POINTER_UP) and the number of pointers falls below MIN_POINTERS
|
262
262
|
// threshold, we only want to take an action when the handler has already activated. Otherwise
|
263
263
|
// we can still expect more fingers to be placed on screen and fulfill MIN_POINTERS criteria.
|
@@ -1,5 +1,6 @@
|
|
1
1
|
package com.swmansion.gesturehandler
|
2
2
|
|
3
|
+
import android.graphics.PointF
|
3
4
|
import android.view.MotionEvent
|
4
5
|
import android.view.ViewConfiguration
|
5
6
|
import kotlin.math.abs
|
@@ -9,10 +10,10 @@ class PinchGestureHandler : GestureHandler<PinchGestureHandler>() {
|
|
9
10
|
private set
|
10
11
|
var velocity = 0.0
|
11
12
|
private set
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
var focalPointX: Float = Float.NaN
|
14
|
+
private set
|
15
|
+
var focalPointY: Float = Float.NaN
|
16
|
+
private set
|
16
17
|
|
17
18
|
private var scaleGestureDetector: ScaleGestureDetector? = null
|
18
19
|
private var startingSpan = 0f
|
@@ -47,7 +48,7 @@ class PinchGestureHandler : GestureHandler<PinchGestureHandler>() {
|
|
47
48
|
}
|
48
49
|
}
|
49
50
|
|
50
|
-
override fun onHandle(event: MotionEvent) {
|
51
|
+
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
|
51
52
|
if (state == STATE_UNDETERMINED) {
|
52
53
|
val context = view!!.context
|
53
54
|
resetProgress()
|
@@ -56,14 +57,19 @@ class PinchGestureHandler : GestureHandler<PinchGestureHandler>() {
|
|
56
57
|
spanSlop = configuration.scaledTouchSlop.toFloat()
|
57
58
|
begin()
|
58
59
|
}
|
59
|
-
scaleGestureDetector?.onTouchEvent(
|
60
|
-
|
61
|
-
|
60
|
+
scaleGestureDetector?.onTouchEvent(sourceEvent)
|
61
|
+
scaleGestureDetector?.let {
|
62
|
+
val point = transformPoint(PointF(it.focusX, it.focusY))
|
63
|
+
this.focalPointX = point.x
|
64
|
+
this.focalPointY = point.y
|
65
|
+
}
|
66
|
+
var activePointers = sourceEvent.pointerCount
|
67
|
+
if (sourceEvent.actionMasked == MotionEvent.ACTION_POINTER_UP) {
|
62
68
|
activePointers -= 1
|
63
69
|
}
|
64
70
|
if (state == STATE_ACTIVE && activePointers < 2) {
|
65
71
|
end()
|
66
|
-
} else if (
|
72
|
+
} else if (sourceEvent.actionMasked == MotionEvent.ACTION_UP) {
|
67
73
|
fail()
|
68
74
|
}
|
69
75
|
}
|
@@ -78,6 +84,8 @@ class PinchGestureHandler : GestureHandler<PinchGestureHandler>() {
|
|
78
84
|
|
79
85
|
override fun onReset() {
|
80
86
|
scaleGestureDetector = null
|
87
|
+
focalPointX = Float.NaN
|
88
|
+
focalPointY = Float.NaN
|
81
89
|
resetProgress()
|
82
90
|
}
|
83
91
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
package com.swmansion.gesturehandler
|
2
2
|
|
3
|
+
import android.graphics.PointF
|
3
4
|
import android.view.MotionEvent
|
4
5
|
import com.swmansion.gesturehandler.RotationGestureDetector.OnRotationGestureListener
|
5
6
|
import kotlin.math.abs
|
@@ -10,11 +11,10 @@ class RotationGestureHandler : GestureHandler<RotationGestureHandler>() {
|
|
10
11
|
private set
|
11
12
|
var velocity = 0.0
|
12
13
|
private set
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
get() = rotationGestureDetector?.anchorY ?: Float.NaN
|
14
|
+
var anchorX: Float = Float.NaN
|
15
|
+
private set
|
16
|
+
var anchorY: Float = Float.NaN
|
17
|
+
private set
|
18
18
|
|
19
19
|
init {
|
20
20
|
setShouldCancelWhenOutside(false)
|
@@ -41,14 +41,19 @@ class RotationGestureHandler : GestureHandler<RotationGestureHandler>() {
|
|
41
41
|
}
|
42
42
|
}
|
43
43
|
|
44
|
-
override fun onHandle(event: MotionEvent) {
|
44
|
+
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
|
45
45
|
if (state == STATE_UNDETERMINED) {
|
46
46
|
resetProgress()
|
47
47
|
rotationGestureDetector = RotationGestureDetector(gestureListener)
|
48
48
|
begin()
|
49
49
|
}
|
50
|
-
rotationGestureDetector?.onTouchEvent(
|
51
|
-
|
50
|
+
rotationGestureDetector?.onTouchEvent(sourceEvent)
|
51
|
+
rotationGestureDetector?.let {
|
52
|
+
val point = transformPoint(PointF(it.anchorX, it.anchorY))
|
53
|
+
anchorX = point.x
|
54
|
+
anchorY = point.y
|
55
|
+
}
|
56
|
+
if (sourceEvent.actionMasked == MotionEvent.ACTION_UP) {
|
52
57
|
if (state == STATE_ACTIVE) {
|
53
58
|
end()
|
54
59
|
} else {
|
@@ -67,6 +72,8 @@ class RotationGestureHandler : GestureHandler<RotationGestureHandler>() {
|
|
67
72
|
|
68
73
|
override fun onReset() {
|
69
74
|
rotationGestureDetector = null
|
75
|
+
anchorX = Float.NaN
|
76
|
+
anchorY = Float.NaN
|
70
77
|
resetProgress()
|
71
78
|
}
|
72
79
|
|