Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions coil-gif/api/coil-gif.api
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
public final class coil/decode/GifDecoder : coil/decode/Decoder {
public static final field ANIMATED_TRANSFORMATION_KEY Ljava/lang/String;
public static final field ANIMATION_END_CALLBACK_KEY Ljava/lang/String;
public static final field ANIMATION_START_CALLBACK_KEY Ljava/lang/String;
public static final field Companion Lcoil/decode/GifDecoder$Companion;
public static final field REPEAT_COUNT_KEY Ljava/lang/String;
public fun <init> ()V
Expand All @@ -12,6 +14,8 @@ public final class coil/decode/GifDecoder$Companion {

public final class coil/decode/ImageDecoderDecoder : coil/decode/Decoder {
public static final field ANIMATED_TRANSFORMATION_KEY Ljava/lang/String;
public static final field ANIMATION_END_CALLBACK_KEY Ljava/lang/String;
public static final field ANIMATION_START_CALLBACK_KEY Ljava/lang/String;
public static final field Companion Lcoil/decode/ImageDecoderDecoder$Companion;
public static final field REPEAT_COUNT_KEY Ljava/lang/String;
public fun <init> ()V
Expand Down Expand Up @@ -81,6 +85,10 @@ public final class coil/drawable/ScaleDrawable : android/graphics/drawable/Drawa
public final class coil/request/Gifs {
public static final fun animatedTransformation (Lcoil/request/ImageRequest$Builder;Lcoil/transform/AnimatedTransformation;)Lcoil/request/ImageRequest$Builder;
public static final fun animatedTransformation (Lcoil/request/Parameters;)Lcoil/transform/AnimatedTransformation;
public static final fun animationEndCallback (Lcoil/request/Parameters;)Lkotlin/jvm/functions/Function0;
public static final fun animationStartCallback (Lcoil/request/Parameters;)Lkotlin/jvm/functions/Function0;
public static final fun onAnimationEnd (Lcoil/request/ImageRequest$Builder;Lkotlin/jvm/functions/Function0;)Lcoil/request/ImageRequest$Builder;
public static final fun onAnimationStart (Lcoil/request/ImageRequest$Builder;Lkotlin/jvm/functions/Function0;)Lcoil/request/ImageRequest$Builder;
public static final fun repeatCount (Lcoil/request/ImageRequest$Builder;I)Lcoil/request/ImageRequest$Builder;
public static final fun repeatCount (Lcoil/request/Parameters;)Ljava/lang/Integer;
}
Expand Down
21 changes: 21 additions & 0 deletions coil-gif/src/main/java/coil/decode/GifDecoder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ package coil.decode

import android.graphics.Bitmap
import android.graphics.Movie
import android.graphics.drawable.Drawable
import android.os.Build.VERSION.SDK_INT
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
import coil.bitmap.BitmapPool
import coil.drawable.MovieDrawable
import coil.request.animatedTransformation
import coil.request.animationEndCallback
import coil.request.animationStartCallback
import coil.request.repeatCount
import coil.size.Size
import okio.BufferedSource
Expand Down Expand Up @@ -54,6 +58,21 @@ class GifDecoder : Decoder {

drawable.setRepeatCount(options.parameters.repeatCount() ?: MovieDrawable.REPEAT_INFINITE)

// Set the start and end animation callbacks if any one is supplied through the request.
if (options.parameters.animationStartCallback() != null || options.parameters.animationEndCallback() != null) {
drawable.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() {
override fun onAnimationStart(drawable: Drawable?) {
super.onAnimationStart(drawable)
Comment thread
sagar-viradiya marked this conversation as resolved.
Outdated
options.parameters.animationStartCallback()?.invoke()
}

override fun onAnimationEnd(drawable: Drawable?) {
super.onAnimationEnd(drawable)
options.parameters.animationEndCallback()?.invoke()
}
})
}

// Set the animated transformation to be applied on each frame.
drawable.setAnimatedTransformation(options.parameters.animatedTransformation())

Expand All @@ -66,5 +85,7 @@ class GifDecoder : Decoder {
companion object {
const val REPEAT_COUNT_KEY = "coil#repeat_count"
const val ANIMATED_TRANSFORMATION_KEY = "coil#animated_transformation"
const val ANIMATION_START_CALLBACK_KEY = "coil#aimation_start_callback"
const val ANIMATION_END_CALLBACK_KEY = "coil#aimation_end_callback"
Comment thread
sagar-viradiya marked this conversation as resolved.
Outdated
}
}
22 changes: 22 additions & 0 deletions coil-gif/src/main/java/coil/decode/ImageDecoderDecoder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ package coil.decode

import android.graphics.Bitmap
import android.graphics.ImageDecoder
import android.graphics.drawable.Animatable2
import android.graphics.drawable.AnimatedImageDrawable
import android.graphics.drawable.Drawable
import android.os.Build.VERSION.SDK_INT
import androidx.annotation.RequiresApi
import androidx.core.graphics.decodeDrawable
Expand All @@ -13,6 +15,8 @@ import androidx.core.util.component2
import coil.bitmap.BitmapPool
import coil.drawable.ScaleDrawable
import coil.request.animatedTransformation
import coil.request.animationEndCallback
import coil.request.animationStartCallback
import coil.request.repeatCount
import coil.size.PixelSize
import coil.size.Size
Expand Down Expand Up @@ -108,6 +112,22 @@ class ImageDecoderDecoder : Decoder {
val drawable = if (baseDrawable is AnimatedImageDrawable) {
baseDrawable.repeatCount = options.parameters.repeatCount() ?: AnimatedImageDrawable.REPEAT_INFINITE

// Set the start and end animation callbacks if any one is supplied through the request.
if (options.parameters.animationStartCallback() != null ||
Comment thread
sagar-viradiya marked this conversation as resolved.
Outdated
options.parameters.animationEndCallback() != null) {
baseDrawable.registerAnimationCallback(object : Animatable2.AnimationCallback() {
override fun onAnimationStart(drawable: Drawable?) {
super.onAnimationStart(drawable)
options.parameters.animationStartCallback()?.invoke()
}

override fun onAnimationEnd(drawable: Drawable?) {
super.onAnimationEnd(drawable)
options.parameters.animationEndCallback()?.invoke()
}
})
}

// Wrap AnimatedImageDrawable in a ScaleDrawable so it always scales to fill its bounds.
ScaleDrawable(baseDrawable, options.scale)
} else {
Expand All @@ -126,5 +146,7 @@ class ImageDecoderDecoder : Decoder {
companion object {
const val REPEAT_COUNT_KEY = GifDecoder.REPEAT_COUNT_KEY
const val ANIMATED_TRANSFORMATION_KEY = GifDecoder.ANIMATED_TRANSFORMATION_KEY
const val ANIMATION_START_CALLBACK_KEY = GifDecoder.ANIMATION_START_CALLBACK_KEY
const val ANIMATION_END_CALLBACK_KEY = GifDecoder.ANIMATION_END_CALLBACK_KEY
}
}
24 changes: 24 additions & 0 deletions coil-gif/src/main/java/coil/request/Gifs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package coil.request
import android.graphics.drawable.AnimatedImageDrawable
import android.graphics.drawable.Drawable
import coil.decode.GifDecoder.Companion.ANIMATED_TRANSFORMATION_KEY
import coil.decode.GifDecoder.Companion.ANIMATION_END_CALLBACK_KEY
import coil.decode.GifDecoder.Companion.ANIMATION_START_CALLBACK_KEY
import coil.decode.GifDecoder.Companion.REPEAT_COUNT_KEY
import coil.drawable.MovieDrawable
import coil.transform.AnimatedTransformation
Expand Down Expand Up @@ -35,3 +37,25 @@ fun ImageRequest.Builder.animatedTransformation(animatedTransformation: Animated
fun Parameters.animatedTransformation(): AnimatedTransformation? {
return value(ANIMATED_TRANSFORMATION_KEY) as AnimatedTransformation?
}

/** Set the callback to be invoked at the start of the animation if the result is an animated [Drawable]. */
fun ImageRequest.Builder.onAnimationStart(callback: (() -> Unit)?): ImageRequest.Builder {
return setParameter(ANIMATION_START_CALLBACK_KEY, callback)
}

/** Get the callback to be invoked at the start of the animation if the result is an animated [Drawable]. */
@Suppress("UNCHECKED_CAST")
Comment thread
sagar-viradiya marked this conversation as resolved.
Outdated
fun Parameters.animationStartCallback(): (() -> Unit)? {
return value(ANIMATION_START_CALLBACK_KEY) as (() -> Unit)?
}

/** Set the callback to be invoked at the end of the animation if the result is an animated [Drawable]. */
fun ImageRequest.Builder.onAnimationEnd(callback: (() -> Unit)?): ImageRequest.Builder {
return setParameter(ANIMATION_END_CALLBACK_KEY, callback)
}

/** Get the callback to be invoked at the end of the animation if the result is an animated [Drawable]. */
@Suppress("UNCHECKED_CAST")
fun Parameters.animationEndCallback(): (() -> Unit)? {
return value(ANIMATION_END_CALLBACK_KEY) as (() -> Unit)?
}