-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
FlingGestureHandler.kt
100 lines (88 loc) · 2.82 KB
/
FlingGestureHandler.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package com.swmansion.gesturehandler.core
import android.os.Handler
import android.os.Looper
import android.view.MotionEvent
class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
var numberOfPointersRequired = DEFAULT_NUMBER_OF_TOUCHES_REQUIRED
var direction = DEFAULT_DIRECTION
private val maxDurationMs = DEFAULT_MAX_DURATION_MS
private val minAcceptableDelta = DEFAULT_MIN_ACCEPTABLE_DELTA
private var startX = 0f
private var startY = 0f
private var handler: Handler? = null
private var maxNumberOfPointersSimultaneously = 0
private val failDelayed = Runnable { fail() }
override fun resetConfig() {
super.resetConfig()
numberOfPointersRequired = DEFAULT_NUMBER_OF_TOUCHES_REQUIRED
direction = DEFAULT_DIRECTION
}
private fun startFling(event: MotionEvent) {
startX = event.rawX
startY = event.rawY
begin()
maxNumberOfPointersSimultaneously = 1
if (handler == null) {
handler = Handler(Looper.getMainLooper()) // lazy delegate?
} else {
handler!!.removeCallbacksAndMessages(null)
}
handler!!.postDelayed(failDelayed, maxDurationMs)
}
private fun tryEndFling(event: MotionEvent) = if (
maxNumberOfPointersSimultaneously == numberOfPointersRequired &&
(
direction and DIRECTION_RIGHT != 0 &&
event.rawX - startX > minAcceptableDelta ||
direction and DIRECTION_LEFT != 0 &&
startX - event.rawX > minAcceptableDelta ||
direction and DIRECTION_UP != 0 &&
startY - event.rawY > minAcceptableDelta ||
direction and DIRECTION_DOWN != 0 &&
event.rawY - startY > minAcceptableDelta
)
) {
handler!!.removeCallbacksAndMessages(null)
activate()
true
} else {
false
}
override fun activate(force: Boolean) {
super.activate(force)
end()
}
private fun endFling(event: MotionEvent) {
if (!tryEndFling(event)) {
fail()
}
}
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
val state = state
if (state == STATE_UNDETERMINED) {
startFling(sourceEvent)
}
if (state == STATE_BEGAN) {
tryEndFling(sourceEvent)
if (sourceEvent.pointerCount > maxNumberOfPointersSimultaneously) {
maxNumberOfPointersSimultaneously = sourceEvent.pointerCount
}
val action = sourceEvent.actionMasked
if (action == MotionEvent.ACTION_UP) {
endFling(sourceEvent)
}
}
}
override fun onCancel() {
handler?.removeCallbacksAndMessages(null)
}
override fun onReset() {
handler?.removeCallbacksAndMessages(null)
}
companion object {
private const val DEFAULT_MAX_DURATION_MS: Long = 800
private const val DEFAULT_MIN_ACCEPTABLE_DELTA: Long = 160
private const val DEFAULT_DIRECTION = DIRECTION_RIGHT
private const val DEFAULT_NUMBER_OF_TOUCHES_REQUIRED = 1
}
}