Skip to content

Instantly share code, notes, and snippets.

@cbeyls
Last active August 1, 2020 02:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbeyls/de8cff03617e375b649a460f8cbca7ba to your computer and use it in GitHub Desktop.
Save cbeyls/de8cff03617e375b649a460f8cbca7ba to your computer and use it in GitHub Desktop.
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