Last active
August 1, 2020 02:32
-
-
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.
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
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