Created
May 6, 2022 05:05
-
-
Save talenguyen/f7908309816746214da4bf47792f2671 to your computer and use it in GitHub Desktop.
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
/** | |
* 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