react-native-gesture-handler 2.6.2 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|