Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A Transition for the Coil image loader that crossfades from the current drawable to a new one, and enables a hardware layer for the duration of the animation if the view is not opaque.
package be.digitalia.bifff.coil
import android.view.View
import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
import coil.annotation.ExperimentalCoilApi
import coil.decode.DataSource
import coil.drawable.CrossfadeDrawable
import coil.request.ErrorResult
import coil.request.RequestResult
import coil.request.SuccessResult
import coil.transition.CrossfadeTransition
import coil.transition.Transition
import coil.transition.TransitionTarget
/** A [Transition] that crossfades from the current drawable to a new one,
* and enables a hardware layer for the duration of the animation if the view is not opaque. */
@ExperimentalCoilApi
class LayerCrossfadeTransition @JvmOverloads constructor(
durationMillis: Int = CrossfadeDrawable.DEFAULT_DURATION
) : Transition {
private val crossfadeTransition = CrossfadeTransition(durationMillis)
override suspend fun transition(
target: TransitionTarget<*>,
result: RequestResult
) {
// Don't animate if the request was fulfilled by the memory cache.
if (result is SuccessResult && result.source == DataSource.MEMORY_CACHE) {
target.onSuccess(result.drawable)
return
}
// Don't animate if the view is not visible as CrossfadeDrawable.onDraw
// won't be called until the view becomes visible.
if (!target.view.isVisible) {
when (result) {
is SuccessResult -> target.onSuccess(result.drawable)
is ErrorResult -> target.onError(result.drawable)
}
return
}
val layerTypeChanged = target.view.alpha < 1.0 && target.view.layerType == View.LAYER_TYPE_NONE
if (layerTypeChanged) {
target.view.setLayerType(View.LAYER_TYPE_HARDWARE, null)
if (ViewCompat.isAttachedToWindow(target.view)) {
target.view.buildLayer()
}
}
try {
// Animate the drawable and suspend until the animation is complete.
crossfadeTransition.transition(target, result)
} finally {
if (layerTypeChanged) {
target.view.post {
target.view.setLayerType(View.LAYER_TYPE_NONE, null)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment