I adopted this solution here: https://github.com/jaredsburrows/android-gif-example/commit/5690523c6dc40c435c3d81868d89ba26d21e3663 since it was removed from Accompanist here.
Code:
class ImageService @Inject constructor(@ApplicationContext private val context: Context) { /** Compose views */ fun loadGif( imageUrl: String, thumbnailUrl: String, onResourceReady: (GifDrawable?) -> Unit, onLoadFailed: () -> Unit, ) { loadGif(imageUrl) .override(SIZE_ORIGINAL, SIZE_ORIGINAL) .thumbnail(loadGif(thumbnailUrl)) .into(object : CustomTarget<GifDrawable>() { override fun onLoadFailed(errorDrawable: Drawable?) { super.onLoadFailed(errorDrawable) onLoadFailed.invoke() } override fun onLoadCleared(placeholder: Drawable?) { onLoadFailed.invoke() } override fun onResourceReady( resource: GifDrawable, transition: Transition<in GifDrawable>?, ) { onResourceReady.invoke(resource) } }) } /** ImageViews */ fun loadGif( imageUrl: String, thumbnailUrl: String, imageView: ImageView, onResourceReady: () -> Unit, onLoadFailed: (GlideException?) -> Unit, ) { loadGif(imageUrl) .override(SIZE_ORIGINAL, SIZE_ORIGINAL) .thumbnail(loadGif(thumbnailUrl)) .listener( object : RequestListener<GifDrawable> { override fun onResourceReady( resource: GifDrawable?, model: Any?, target: Target<GifDrawable>?, dataSource: DataSource?, isFirstResource: Boolean ): Boolean { onResourceReady.invoke() return false } override fun onLoadFailed( e: GlideException?, model: Any?, target: Target<GifDrawable>?, isFirstResource: Boolean ): Boolean { onLoadFailed.invoke(e) return false } } ) .into(imageView) .clearOnDetach() } private fun loadGif(imageUrl: String): RequestBuilder<GifDrawable> { return GlideApp.with(context) .asGif() .transition(withCrossFade()) .load(imageUrl) } }
See the code here: https://github.com/jaredsburrows/android-gif-example/blob/52914cd63b528b3a9365df6bfa2134ffdfa0e0d7/app/src/main/java/com/burrowsapps/example/gif/data/ImageService.kt#L22
Usage:
composeView.setContent { val showProgressBar = remember { mutableStateOf(true) } val state = remember { mutableStateOf<GifDrawable?>(null) } GifTheme { // Load images - 'tinyGifPreviewUrl' -> 'tinyGifUrl' imageService.loadGif( imageUrl = imageInfoModel.tinyGifUrl, thumbnailUrl = imageInfoModel.tinyGifPreviewUrl, onResourceReady = { resource -> showProgressBar.value = false state.value = resource }, onLoadFailed = { showProgressBar.value = false state.value = null }, ) // Show loading indicator when image is not loaded if (showProgressBar.value) { CircularProgressIndicator( modifier = Modifier .fillMaxWidth() .height(128.dp) .padding(all = 24.dp), ) } else { Image( painter = rememberDrawablePainter(drawable = state.value), contentDescription = stringResource(id = R.string.gif_image), contentScale = ContentScale.Crop, modifier = Modifier .fillMaxWidth() .height(135.dp), ) } } }
See the code here: https://github.com/jaredsburrows/android-gif-example/blob/52914cd63b528b3a9365df6bfa2134ffdfa0e0d7/app/src/main/java/com/burrowsapps/example/gif/ui/giflist/GifAdapter.kt#L73
Quick questionit's usually these which are the hardest to answer :)Viewsystem? At least for the first several years of Android's existence,ImageViewwould not animate a GIF, for example. Developers wound up usingWebVieworMovie(IIRC) until a bunch of animated-GIF-capable rendering libraries became available. Your question suggests that you expect animation, but is that a reasonable expectation?