Skip to content

Instantly share code, notes, and snippets.

@madushans
Last active January 9, 2024 20:43
Show Gist options
  • Save madushans/5a251bdf6d07745495f316a4f232c36e to your computer and use it in GitHub Desktop.
Save madushans/5a251bdf6d07745495f316a4f232c36e to your computer and use it in GitHub Desktop.
Load images with blurred thumbnail load effect using Jetpack Compose, Glide and StateFlow
// Adapted from https://gist.github.com/lelandrichardson/de674fe6788d922fc84362fdae530464
@Composable
fun ExampleUsage(){
GlideImage(src = "source-path",
blurThumbSrc = "fast-to-load-small-thumbnail-path-for-blur effect"
){imageBitmap ->
if (imageBitmap != null) {
Image(bitmap = imageBitmap,
// modifier = ...
)
}
else {
// handle fallback
// i.e. net disconnected or both urls failed .etc.
}
}
}
fun GlideImage(src: String,
blurThumbSrc: String? = null,
content: @Composable (ImageBitmap?) -> Unit) {
val view = AmbientView.current
val density = AmbientDensity.current
WithConstraints {
val width = with(density) { maxWidth.toIntPx() }
val height = with(density) { maxHeight.toIntPx() }
val flow = remember(src, blurThumbSrc) {
loadImage(
view,
width,
height,
src,
blurThumbSrc)
}.collectAsState()
content(flow.value?.asImageBitmap())
}
}
private fun loadImage(view: View,
width:Int,
height:Int,
src: String,
blurThumbnailSrc: String?): StateFlow<Bitmap?> {
val resultFlow = MutableStateFlow<Bitmap?>(null)
val listener = GlideRequestListener(resultFlow)
var glide = Glide
.with(view)
.asBitmap()
if (blurThumbnailSrc != null) {
val thumbnailBuilder = Glide
.with(view.context)
.asBitmap()
.load(blurThumbnailSrc)
.override(width, height) // scale up so the soft blur looks nicer.
.addListener(listener)
.transform(BlurTransformation(70, 3))
glide = glide.thumbnail(thumbnailBuilder)
}
glide
.load(src)
.addListener(listener)
.preload()
return resultFlow
}
private class GlideRequestListener(val resultFlow: MutableStateFlow<Bitmap?>):RequestListener<Bitmap> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Bitmap>?,
isFirstResource: Boolean
): Boolean {
e!!.printStackTrace()
return false
}
override fun onResourceReady(
resource: Bitmap?,
_model: Any?,
target: Target<Bitmap>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
resultFlow.value = resource
return true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment