Skip to content

Instantly share code, notes, and snippets.

@talenguyen
Created May 6, 2022 05:05
Show Gist options
  • Save talenguyen/f7908309816746214da4bf47792f2671 to your computer and use it in GitHub Desktop.
Save talenguyen/f7908309816746214da4bf47792f2671 to your computer and use it in GitHub Desktop.
/**
* Source: https://medium.com/androiddevelopers/suspending-over-views-19de9ebd7020
*/
suspend fun Animator.awaitEnd() = suspendCancellableCoroutine<Unit> { cont ->
// Add an invokeOnCancellation listener. If the coroutine is
// cancelled, cancel the animation too that will notify
// listener's onAnimationCancel() function
cont.invokeOnCancellation { cancel() }
addListener(object : AnimatorListenerAdapter() {
private var endedSuccessfully = true
override fun onAnimationCancel(animation: Animator) {
// Animator has been cancelled, so flip the success flag
endedSuccessfully = false
}
override fun onAnimationEnd(animation: Animator) {
// Make sure we remove the listener so we don't keep
// leak the coroutine continuation
animation.removeListener(this)
if (cont.isActive) {
// If the coroutine is still active...
if (endedSuccessfully) {
// ...and the Animator ended successfully, resume the coroutine
cont.resume(Unit)
} else {
// ...and the Animator was cancelled, cancel the coroutine too
cont.cancel()
}
}
}
})
}
/**
* Source: https://medium.com/androiddevelopers/suspending-over-views-19de9ebd7020
*/
suspend fun View.awaitNextLayout() = suspendCancellableCoroutine<Unit> { cont ->
// This lambda is invoked immediately, allowing us to create
// a callback/listener
val listener = object : View.OnLayoutChangeListener {
override fun onLayoutChange(...) {
// The next layout has happened!
// First remove the listener to not leak the coroutine
view.removeOnLayoutChangeListener(this)
// Finally resume the continuation, and
// wake the coroutine up
cont.resume(Unit)
}
}
// If the coroutine is cancelled, remove the listener
cont.invokeOnCancellation { removeOnLayoutChangeListener(listener) }
// And finally add the listener to view
addOnLayoutChangeListener(listener)
// The coroutine will now be suspended. It will only be resumed
// when calling cont.resume() in the listener above
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment