Last active
June 29, 2022 15:36
-
-
Save RafhaanShah/14136eeedea87b64178925a9f45de049 to your computer and use it in GitHub Desktop.
Android onHoldListener that calls a callback periodically while a view is being held, works for clicks as well.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun View.setOnHoldListener( | |
firstClickDelayMillis: Long = 250L, | |
tickDelayMillis: Long = 100L, | |
onRelease: () -> Unit = {}, | |
onTick: (Int) -> Unit | |
) { | |
val lifeCycleOwner = findViewTreeLifecycleOwner() ?: return | |
var job: Job? = null | |
// cancel this job if the lifeCycleOwner is ever paused | |
// just in case we reach this state without MotionEvent.ACTION_UP on the touchListener | |
lifeCycleOwner.lifecycle.addObserver(object : LifecycleEventObserver { | |
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) { | |
when (event) { | |
Lifecycle.Event.ON_PAUSE -> { | |
job?.cancel() | |
job = null | |
} | |
else -> {} | |
} | |
} | |
}) | |
// added for accessibility, resolves lint issue ClickableViewAccessibility | |
setOnClickListener { | |
job?.cancel() // just in case the job is already running | |
job = lifeCycleOwner.lifecycleScope.launch { | |
var counter = 0 | |
onTick(counter++) | |
delay(firstClickDelayMillis) | |
// call onTick() every tick, while the job is active | |
while (true) { | |
ensureActive() | |
onTick(counter++) | |
delay(tickDelayMillis) | |
} | |
} | |
} | |
setOnTouchListener { _, event -> | |
return@setOnTouchListener when (event.action) { | |
// triggers onClick() when this view is touched | |
MotionEvent.ACTION_DOWN -> { | |
isPressed = true | |
performClick() | |
true | |
} | |
// cancels the job and ticking the view is no longer being touched | |
MotionEvent.ACTION_UP -> { | |
isPressed = false | |
job?.cancel() | |
job = null | |
onRelease() | |
true | |
} | |
else -> false | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment