Skip to content

Commit 3205ed4

Browse files
committed
Add gesture initialization
1 parent 1091a01 commit 3205ed4

File tree

8 files changed

+89
-58
lines changed

8 files changed

+89
-58
lines changed

android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandler.kt

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
5757
var lastAbsolutePositionY = 0f
5858
private set
5959

60+
private var isInitialized = false
6061
private var manualActivation = false
6162

6263
private var lastEventOffsetX = 0f
@@ -68,6 +69,8 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
6869
private var onTouchEventListener: OnTouchEventListener? = null
6970
private var interactionController: GestureHandlerInteractionController? = null
7071

72+
private var eventTriggeringStateChangeInTouchEventHandler: MotionEvent? = null
73+
7174
@Suppress("UNCHECKED_CAST")
7275
protected fun self(): ConcreteGestureHandlerT = this as ConcreteGestureHandlerT
7376

@@ -88,8 +91,8 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
8891
onTouchEventListener?.onHandlerUpdate(self(), event)
8992
}
9093

91-
open fun dispatchTouchEvent() {
92-
if (changedTouchesPayload != null) {
94+
open fun tryDispatchingTouchEvent() {
95+
if (needsPointerData && changedTouchesPayload != null) {
9396
onTouchEventListener?.onTouchEvent(self())
9497
}
9598
}
@@ -372,7 +375,7 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
372375
}
373376
}
374377

375-
private fun dispatchTouchDownEvent(event: MotionEvent) {
378+
private fun handleTouchDownEvent(event: MotionEvent) {
376379
changedTouchesPayload = null
377380
touchEventType = RNGestureHandlerTouchEvent.EVENT_TOUCH_DOWN
378381
val pointerId = event.getPointerId(event.actionIndex)
@@ -390,10 +393,10 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
390393
addChangedPointer(trackedPointers[pointerId]!!)
391394
extractAllPointersData()
392395

393-
dispatchTouchEvent()
396+
tryDispatchingTouchEvent()
394397
}
395398

396-
private fun dispatchTouchUpEvent(event: MotionEvent) {
399+
private fun handleTouchUpEvent(event: MotionEvent) {
397400
extractAllPointersData()
398401
changedTouchesPayload = null
399402
touchEventType = RNGestureHandlerTouchEvent.EVENT_TOUCH_UP
@@ -412,10 +415,10 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
412415
trackedPointers[pointerId] = null
413416
trackedPointersCount--
414417

415-
dispatchTouchEvent()
418+
tryDispatchingTouchEvent()
416419
}
417420

418-
private fun dispatchTouchMoveEvent(event: MotionEvent) {
421+
private fun handleTouchMoveEvent(event: MotionEvent) {
419422
changedTouchesPayload = null
420423
touchEventType = RNGestureHandlerTouchEvent.EVENT_TOUCH_MOVE
421424
val offsetX = event.rawX - event.x
@@ -442,20 +445,28 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
442445
// only info about one pointer)
443446
if (pointersAdded > 0) {
444447
extractAllPointersData()
445-
dispatchTouchEvent()
448+
tryDispatchingTouchEvent()
446449
}
447450
}
448451

449-
fun updatePointerData(event: MotionEvent) {
450-
if (event.actionMasked == MotionEvent.ACTION_DOWN || event.actionMasked == MotionEvent.ACTION_POINTER_DOWN) {
451-
dispatchTouchDownEvent(event)
452-
dispatchTouchMoveEvent(event)
453-
} else if (event.actionMasked == MotionEvent.ACTION_UP || event.actionMasked == MotionEvent.ACTION_POINTER_UP) {
454-
dispatchTouchMoveEvent(event)
455-
dispatchTouchUpEvent(event)
456-
} else if (event.actionMasked == MotionEvent.ACTION_MOVE) {
457-
dispatchTouchMoveEvent(event)
452+
fun updatePointerData(event: MotionEvent, sourceEvent: MotionEvent) {
453+
eventTriggeringStateChangeInTouchEventHandler = sourceEvent
454+
455+
when (event.actionMasked) {
456+
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
457+
handleTouchDownEvent(event)
458+
handleTouchMoveEvent(event)
459+
}
460+
MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
461+
handleTouchMoveEvent(event)
462+
handleTouchUpEvent(event)
463+
}
464+
MotionEvent.ACTION_MOVE -> {
465+
handleTouchMoveEvent(event)
466+
}
458467
}
468+
469+
eventTriggeringStateChangeInTouchEventHandler = null
459470
}
460471

461472
private fun extractAllPointersData() {
@@ -482,7 +493,7 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
482493
trackedPointersCount = 0
483494
trackedPointers.fill(null)
484495

485-
dispatchTouchEvent()
496+
tryDispatchingTouchEvent()
486497
}
487498

488499
private fun addChangedPointer(pointerData: PointerData) {
@@ -659,6 +670,17 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
659670
}
660671
}
661672

673+
fun initialize(withEvent: MotionEvent? = null) {
674+
if (!isInitialized) {
675+
val event = withEvent ?: eventTriggeringStateChangeInTouchEventHandler ?: throw IllegalStateException("No event to initialize handler")
676+
onInitialize(event)
677+
}
678+
679+
isInitialized = true
680+
}
681+
682+
open fun onInitialize(event: MotionEvent) {}
683+
662684
// responsible for resetting the state of handler upon activation (may be called more than once
663685
// if the handler is waiting for failure of other one)
664686
open fun resetProgress() {}
@@ -695,6 +717,7 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
695717
trackedPointersCount = 0
696718
trackedPointers.fill(null)
697719
touchEventType = RNGestureHandlerTouchEvent.EVENT_UNDETERMINED
720+
isInitialized = false
698721
onReset()
699722
}
700723

@@ -774,7 +797,7 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
774797
}
775798
}
776799

777-
private data class PointerData(
800+
data class PointerData(
778801
val pointerId: Int,
779802
var x: Float,
780803
var y: Float,

android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandlerOrchestrator.kt

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -253,21 +253,10 @@ class GestureHandlerOrchestrator(
253253

254254
val action = sourceEvent.actionMasked
255255
val event = transformEventToViewCoords(handler.view, MotionEvent.obtain(sourceEvent))
256-
257-
// Touch events are sent before the handler itself has a chance to process them,
258-
// mainly because `onTouchesUp` shoul be send befor gesture finishes. This means that
259-
// the first `onTouchesDown` event is sent before a gesture begins, activation in
260-
// callback for this event causes problems because the handler doesn't have a chance
261-
// to initialize itself with starting values of pointer (in pan this causes translation
262-
// to be equal to the coordinates of the pointer). The simplest solution is to send
263-
// the first `onTouchesDown` event after the handler processes it and changes state
264-
// to `BEGAN`.
265-
if (handler.needsPointerData && handler.state != 0) {
266-
handler.updatePointerData(event)
267-
}
256+
257+
handler.updatePointerData(event, sourceEvent)
268258

269259
if (!handler.isAwaiting || action != MotionEvent.ACTION_MOVE) {
270-
val isFirstEvent = handler.state == 0
271260
handler.handle(event, sourceEvent)
272261
if (handler.isActive) {
273262
// After handler is done waiting for other one to fail its progress should be
@@ -284,10 +273,6 @@ class GestureHandlerOrchestrator(
284273
handler.dispatchHandlerUpdate(event)
285274
}
286275

287-
if (handler.needsPointerData && isFirstEvent) {
288-
handler.updatePointerData(event)
289-
}
290-
291276
// if event was of type UP or POINTER_UP we request handler to stop tracking now that
292277
// the event has been dispatched
293278
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {

android/lib/src/main/java/com/swmansion/gesturehandler/LongPressGestureHandler.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,8 @@ class LongPressGestureHandler(context: Context) : GestureHandler<LongPressGestur
3939

4040
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
4141
if (state == STATE_UNDETERMINED) {
42-
previousTime = SystemClock.uptimeMillis()
43-
startTime = previousTime
42+
initialize(sourceEvent)
4443
begin()
45-
startX = sourceEvent.rawX
46-
startY = sourceEvent.rawY
4744
handler = Handler(Looper.getMainLooper())
4845
if (minDurationMs > 0) {
4946
handler!!.postDelayed({ activate() }, minDurationMs)
@@ -83,6 +80,13 @@ class LongPressGestureHandler(context: Context) : GestureHandler<LongPressGestur
8380
}
8481
}
8582

83+
override fun onInitialize(event: MotionEvent) {
84+
previousTime = SystemClock.uptimeMillis()
85+
startTime = previousTime
86+
startX = event.rawX
87+
startY = event.rawY
88+
}
89+
8690
override fun dispatchStateChange(newState: Int, prevState: Int) {
8791
previousTime = SystemClock.uptimeMillis()
8892
super.dispatchStateChange(newState, prevState)

android/lib/src/main/java/com/swmansion/gesturehandler/PanGestureHandler.kt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,7 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
223223
lastY = getLastPointerY(sourceEvent, averageTouches)
224224
}
225225
if (state == STATE_UNDETERMINED && sourceEvent.pointerCount >= minPointers) {
226-
resetProgress()
227-
offsetX = 0f
228-
offsetY = 0f
229-
velocityX = 0f
230-
velocityY = 0f
231-
velocityTracker = VelocityTracker.obtain()
226+
initialize(sourceEvent)
232227
addVelocityMovement(velocityTracker, sourceEvent)
233228
begin()
234229

@@ -283,6 +278,15 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
283278
handler?.removeCallbacksAndMessages(null)
284279
}
285280

281+
override fun onInitialize(event: MotionEvent) {
282+
resetProgress()
283+
offsetX = 0f
284+
offsetY = 0f
285+
velocityX = 0f
286+
velocityY = 0f
287+
velocityTracker = VelocityTracker.obtain()
288+
}
289+
286290
override fun onReset() {
287291
handler?.removeCallbacksAndMessages(null)
288292
velocityTracker?.let {

android/lib/src/main/java/com/swmansion/gesturehandler/PinchGestureHandler.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,7 @@ class PinchGestureHandler : GestureHandler<PinchGestureHandler>() {
5050

5151
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
5252
if (state == STATE_UNDETERMINED) {
53-
val context = view!!.context
54-
resetProgress()
55-
scaleGestureDetector = ScaleGestureDetector(context, gestureListener)
56-
val configuration = ViewConfiguration.get(context)
57-
spanSlop = configuration.scaledTouchSlop.toFloat()
53+
initialize(sourceEvent)
5854
begin()
5955
}
6056
scaleGestureDetector?.onTouchEvent(sourceEvent)
@@ -89,6 +85,14 @@ class PinchGestureHandler : GestureHandler<PinchGestureHandler>() {
8985
resetProgress()
9086
}
9187

88+
override fun onInitialize(event: MotionEvent) {
89+
resetProgress()
90+
val context = view!!.context
91+
val configuration = ViewConfiguration.get(context)
92+
scaleGestureDetector = ScaleGestureDetector(context, gestureListener)
93+
spanSlop = configuration.scaledTouchSlop.toFloat()
94+
}
95+
9296
override fun resetProgress() {
9397
velocity = 0.0
9498
scale = 1.0

android/lib/src/main/java/com/swmansion/gesturehandler/RotationGestureHandler.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ class RotationGestureHandler : GestureHandler<RotationGestureHandler>() {
4343

4444
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
4545
if (state == STATE_UNDETERMINED) {
46-
resetProgress()
47-
rotationGestureDetector = RotationGestureDetector(gestureListener)
46+
initialize(sourceEvent)
4847
begin()
4948
}
5049
rotationGestureDetector?.onTouchEvent(sourceEvent)
@@ -70,6 +69,11 @@ class RotationGestureHandler : GestureHandler<RotationGestureHandler>() {
7069
super.activate(force)
7170
}
7271

72+
override fun onInitialize(event: MotionEvent) {
73+
resetProgress()
74+
rotationGestureDetector = RotationGestureDetector(gestureListener)
75+
}
76+
7377
override fun onReset() {
7478
rotationGestureDetector = null
7579
anchorX = Float.NaN

android/lib/src/main/java/com/swmansion/gesturehandler/TapGestureHandler.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,7 @@ class TapGestureHandler : GestureHandler<TapGestureHandler>() {
108108
val state = state
109109
val action = sourceEvent.actionMasked
110110
if (state == STATE_UNDETERMINED) {
111-
offsetX = 0f
112-
offsetY = 0f
113-
startX = getLastPointerX(sourceEvent, true)
114-
startY = getLastPointerY(sourceEvent, true)
111+
initialize(sourceEvent)
115112
}
116113
if (action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN) {
117114
offsetX += lastX - startX
@@ -148,6 +145,13 @@ class TapGestureHandler : GestureHandler<TapGestureHandler>() {
148145
end()
149146
}
150147

148+
override fun onInitialize(event: MotionEvent) {
149+
offsetX = 0f
150+
offsetY = 0f
151+
startX = getLastPointerX(event, true)
152+
startY = getLastPointerY(event, true)
153+
}
154+
151155
override fun onCancel() {
152156
handler?.removeCallbacksAndMessages(null)
153157
}

android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,9 +433,12 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
433433

434434
override fun setGestureHandlerState(handlerTag: Int, newState: Int) {
435435
registry.getHandler(handlerTag)?.let { handler ->
436+
handler.initialize()
437+
handler.begin()
438+
436439
when (newState) {
437440
GestureHandler.STATE_ACTIVE -> handler.activate(force = true)
438-
GestureHandler.STATE_BEGAN -> handler.begin()
441+
GestureHandler.STATE_BEGAN -> {}
439442
GestureHandler.STATE_END -> handler.end()
440443
GestureHandler.STATE_FAILED -> handler.fail()
441444
GestureHandler.STATE_CANCELLED -> handler.cancel()

0 commit comments

Comments
 (0)