Skip to content

Instantly share code, notes, and snippets.

@marcelpinto
Created November 8, 2022 11:36
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcelpinto/6df5e3e6ca42c6a0bf34b9f4b6eb1cff to your computer and use it in GitHub Desktop.
Save marcelpinto/6df5e3e6ca42c6a0bf34b9f4b6eb1cff to your computer and use it in GitHub Desktop.
ImageGlanceWidget using recomposition + coil
// Copyright 2022 Google LLC.
// SPDX-License-Identifier: Apache-2.0
import android.content.Context
import android.graphics.Bitmap
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.unit.DpSize
import androidx.core.graphics.drawable.toBitmapOrNull
import androidx.glance.GlanceModifier
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.LocalContext
import androidx.glance.LocalSize
import androidx.glance.action.clickable
import androidx.glance.appwidget.CircularProgressIndicator
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import androidx.glance.appwidget.SizeMode
import androidx.glance.layout.ContentScale
import androidx.glance.layout.fillMaxSize
import androidx.glance.session.GlanceSessionManager
import coil.imageLoader
import coil.request.CachePolicy
import coil.request.ErrorResult
import coil.request.ImageRequest
import coil.request.SuccessResult
import kotlinx.coroutines.launch
import kotlin.math.roundToInt
/**
* Sample showcasing how to load images using Coil.
*/
class ImageGlanceWidget : GlanceAppWidget() {
override val sessionManager = GlanceSessionManager
override val sizeMode: SizeMode = SizeMode.Exact
@Composable
override fun Content() {
val context = LocalContext.current
val url = getImageUrl(LocalSize.current)
val scope = rememberCoroutineScope()
var randomImage by remember(url) { mutableStateOf<Bitmap?>(null) }
// Load a random image
LaunchedEffect(url) {
randomImage = context.getRandomImage(url)
}
if (randomImage != null) {
Image(
provider = ImageProvider(randomImage!!),
contentDescription = "Image from Picsum Photos",
contentScale = ContentScale.FillBounds,
modifier = GlanceModifier.fillMaxSize().clickable {
scope.launch {
randomImage = context.getRandomImage(url, force = true)
}
}
)
} else {
CircularProgressIndicator()
}
}
private fun getImageUrl(size: DpSize) =
"https://picsum.photos/${size.width.value.roundToInt()}/${size.height.value.roundToInt()}"
private suspend fun Context.getRandomImage(url: String, force: Boolean = false): Bitmap? {
val request = ImageRequest.Builder(this).data(url).apply {
if (force) {
memoryCachePolicy(CachePolicy.DISABLED)
diskCachePolicy(CachePolicy.DISABLED)
}
}.build()
// Request the image to be loaded and throw error if it failed
return when (val result = imageLoader.execute(request)) {
is ErrorResult -> throw result.throwable
is SuccessResult -> result.drawable.toBitmapOrNull()
}
}
}
class ImageGlanceWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = ImageGlanceWidget()
}
@marcelpinto
Copy link
Author

glance-recomposition-coil

@DawnNguyenAhiho
Copy link

Hello, how are things going? Looking forward to seeing Coil integrated and used in Glance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment