-
-
Save tieorange/97aed21a2633bceae13261c1c5948cbd to your computer and use it in GitHub Desktop.
package com.westwingnow.android.utils | |
import android.os.SystemClock | |
import android.view.View | |
import java.util.* | |
/** | |
* A Throttled OnClickListener | |
* Rejects clicks that are too close together in time. | |
* This class is safe to use as an OnClickListener for multiple views, and will throttle each one separately. | |
* | |
* * @param minimumIntervalMsec The minimum allowed time between clicks - any click sooner than this after a previous click will be rejected | |
*/ | |
private const val minimumInterval = 1000L | |
class ThrottledOnClickListener(private val onClick: (view: View) -> Unit) : View.OnClickListener { | |
private val lastClickMap: MutableMap<View, Long> = WeakHashMap() | |
override fun onClick(clickedView: View) { | |
val previousClickTimestamp = lastClickMap[clickedView] | |
val currentTimestamp = SystemClock.uptimeMillis() | |
lastClickMap[clickedView] = currentTimestamp | |
if (previousClickTimestamp == null || currentTimestamp - previousClickTimestamp.toLong() > minimumInterval) { | |
onClick.invoke(clickedView) | |
} | |
} | |
} |
can you please give an example of how to use this class with a button. thank you
val button: Button = view.findViewById(R.id.button)
val buttonClickListener = ThrottledOnClickListener {
// do something
}
button.setOnClickListener(buttonClickListener)
You can also write an extension function to use this as button.setThrottledOnClickListener { }
There is an error on 25 line, it's a recursive call. There needs to be onClick.invoke(clickedView)
to use the lambda passed in the constructor.
I'll advise you use androidrx/rxjava library, it comes with throttle operator
Already solved, thanks for the great class
I think, androidrx/rxjava library is too heavy for just debounce or throttle
There is an error on 25 line, it's a recursive call. There needs to be
onClick.invoke(clickedView)
to use the lambda passed in the constructor.
Thumbs up for this.
@artnest @tieorange
Is there a particular reason to create a separate class for it. Can't we do it as an extension function on View
class? Something like this:
fun View.setDebouncedClickListener(
debounceIntervalMs: Int = 700,
listener: (view: View?) -> Unit
) {
var lastTapTimestamp: Long = 0
val customListener = View.OnClickListener {
val currentTime = System.currentTimeMillis()
if (currentTime - lastTapTimestamp > debounceIntervalMs) {
lastTapTimestamp = currentTime
listener(it)
}
}
this.setOnClickListener(customListener)
}
There is an error on 25 line, it's a recursive call. There needs to be
onClick.invoke(clickedView)
to use the lambda passed in the constructor.
Works like a charm!
Maybe edit the gist to correct the error.
There is an error on 25 line, it's a recursive call. There needs to be
onClick.invoke(clickedView)
to use the lambda passed in the constructor.Works like a charm!
Maybe edit the gist to correct the error.
Fixed. Thanks!
can you please give an example of how to use this class with a button. thank you