Last active
December 30, 2023 12:45
-
-
Save kishan-vadoliya/85c7500a2d46622c5f6363f239f8035e to your computer and use it in GitHub Desktop.
ImageGlanceWidget using recomposition + coil
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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() | |
} |
Author
kishan-vadoliya
commented
Oct 19, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment