Merge pull request #121 from TouchInstinct/feature/click_throttling

Add throttling in `View.setOnRippleClickListener()` implementation to prevent multiple actions during ripple delay
This commit is contained in:
Даниил Борисовский 2020-04-14 16:32:40 +03:00 committed by GitHub
commit aaf256b5e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 2 deletions

View File

@ -2,8 +2,9 @@ package ru.touchin.extensions
import android.os.Build
import android.view.View
import ru.touchin.utils.ActionThrottler
private const val RIPPLE_EFFECT_DELAY = 150L
const val RIPPLE_EFFECT_DELAY_MS = 150L
/**
* Sets click listener to view. On click it will call something after delay.
@ -12,7 +13,11 @@ private const val RIPPLE_EFFECT_DELAY = 150L
*/
fun View.setOnRippleClickListener(listener: () -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setOnClickListener { postDelayed({ if (hasWindowFocus()) listener() }, RIPPLE_EFFECT_DELAY) }
setOnClickListener {
ActionThrottler.throttleAction {
postDelayed({ if (hasWindowFocus()) listener() }, RIPPLE_EFFECT_DELAY_MS)
}
}
} else {
setOnClickListener { listener() }
}

View File

@ -0,0 +1,27 @@
package ru.touchin.utils
import android.os.SystemClock
import ru.touchin.extensions.RIPPLE_EFFECT_DELAY_MS
object ActionThrottler {
// It is necessary because in interval after ripple effect finish and before
// action invoking start user may be in time to click and launch action again
private const val PREVENTION_OF_CLICK_AGAIN_COEFFICIENT = 2
private const val DELAY_MS = PREVENTION_OF_CLICK_AGAIN_COEFFICIENT * RIPPLE_EFFECT_DELAY_MS
private var lastActionTime = 0L
fun throttleAction(action: () -> Unit): Boolean {
val currentTime = SystemClock.elapsedRealtime()
val diff = currentTime - lastActionTime
return if (diff >= DELAY_MS) {
lastActionTime = currentTime
action.invoke()
true
} else {
false
}
}
}