-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
LongPressGestureHandler.kt
100 lines (89 loc) · 2.72 KB
/
LongPressGestureHandler.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
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.SystemClock
import android.view.MotionEvent
class LongPressGestureHandler(context: Context) : GestureHandler<LongPressGestureHandler>() {
var minDurationMs = DEFAULT_MIN_DURATION_MS
val duration: Int
get() = (previousTime - startTime).toInt()
private val defaultMaxDistSq: Float
private var maxDistSq: Float
private var startX = 0f
private var startY = 0f
private var startTime: Long = 0
private var previousTime: Long = 0
private var handler: Handler? = null
init {
setShouldCancelWhenOutside(true)
val defaultMaxDist = DEFAULT_MAX_DIST_DP * context.resources.displayMetrics.density
defaultMaxDistSq = defaultMaxDist * defaultMaxDist
maxDistSq = defaultMaxDistSq
}
override fun resetConfig() {
super.resetConfig()
minDurationMs = DEFAULT_MIN_DURATION_MS
maxDistSq = defaultMaxDistSq
}
fun setMaxDist(maxDist: Float): LongPressGestureHandler {
maxDistSq = maxDist * maxDist
return this
}
override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
if (state == STATE_UNDETERMINED) {
previousTime = SystemClock.uptimeMillis()
startTime = previousTime
begin()
startX = sourceEvent.rawX
startY = sourceEvent.rawY
handler = Handler(Looper.getMainLooper())
if (minDurationMs > 0) {
handler!!.postDelayed({ activate() }, minDurationMs)
} else if (minDurationMs == 0L) {
activate()
}
}
if (sourceEvent.actionMasked == MotionEvent.ACTION_UP) {
handler?.let {
it.removeCallbacksAndMessages(null)
handler = null
}
if (state == STATE_ACTIVE) {
end()
} else {
fail()
}
} else {
// calculate distance from start
val deltaX = sourceEvent.rawX - startX
val deltaY = sourceEvent.rawY - startY
val distSq = deltaX * deltaX + deltaY * deltaY
if (distSq > maxDistSq) {
if (state == STATE_ACTIVE) {
cancel()
} else {
fail()
}
}
}
}
override fun onStateChange(newState: Int, previousState: Int) {
handler?.let {
it.removeCallbacksAndMessages(null)
handler = null
}
}
override fun dispatchStateChange(newState: Int, prevState: Int) {
previousTime = SystemClock.uptimeMillis()
super.dispatchStateChange(newState, prevState)
}
override fun dispatchHandlerUpdate(event: MotionEvent) {
previousTime = SystemClock.uptimeMillis()
super.dispatchHandlerUpdate(event)
}
companion object {
private const val DEFAULT_MIN_DURATION_MS: Long = 500
private const val DEFAULT_MAX_DIST_DP = 10f
}
}