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