Add a shimmer while loading an image using coil and compose - android

Loading an image from a web URL and displaying a shimmer during load. Are there any better ways to handle this?
val context = LocalContext.current
val imageLoader = ImageLoader(context)
val request = ImageRequest.Builder(context)
.data(thumbnailUrl)
.build()
val painter = rememberImagePainter(
request = request,
imageLoader = imageLoader
)
val state = painter.state
Image(
painter = painter,
contentDescription = "thumbnail image",
modifier = Modifier
.fillMaxSize()
.placeholder(
visible = state is
ImagePainter.State.Loading,
color = PlaceholderDefaults.color(
backgroundColor = MyTheme.colors.shimmer.copy(0.1f),
),
highlight = PlaceholderHighlight.shimmer(),
),
contentScale = ContentScale.Crop
)
How would you add a token to this request? I tried setting the header with a token but no response. Any suggestions?

Related

Image isn't being loaded by Coil Kotlin Jetpack Compose

I have this image I want to load, I am using coil in jetpack compose to try and load it yet it didn't load and just gave me an empty composable. Whenever I try to load a different image from any other website it works, yet when I use the same website I am loading this image from. It doesn't Work.
Here is My Code:
#Composable
fun BookItem(
title: String,
cover: String?,
unreadChapters: Int,
) {
Box(
modifier = Modifier
.wrapContentSize(),
contentAlignment = Alignment.Center
) {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(cover)
.crossfade(true)
.build(),
contentDescription = title,
contentScale = ContentScale.Inside,
modifier = Modifier
.clip(RoundedCornerShape(size = 12.dp))
.size(200.dp)
)
}
}
Here is the link:
https://static.lightnovelworld.com/bookcover/300x400/01365-shadow-slave.jpg
I tried using glide instead of coil and I got the same problem.
Thanks and Regards
You can debug it using:
val imageLoader = LocalContext.current.imageLoader.newBuilder()
.logger(DebugLogger())
.build()
AsyncImage(
//...
imageLoader = imageLoader,
)
Result:
🚨 Failed - https://static.lightnovelworld.com/bookcover/300x400/01365-shadow-slave.jpg - coil.network.HttpException: HTTP 403:
You can try to add some headers in you requests using something like:
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(url)
.setHeader("User-Agent", "Mozilla/5.0")
.build(),
//
)

Jetpack Compose Coil Preload

I want to load the image on the spash screen so that I can set the request result to the background on other screens using the coil, but I have not been able to fully realize this in the coil. How can I save the result of my coil request to Cahce and use this result on other screens?
Splash Screen
val imageLoader = ImageLoader.Builder(this)
.memoryCache {
MemoryCache.Builder(this)
.maxSizePercent(0.25)
.strongReferencesEnabled(true)
.build()
}
.diskCache {
DiskCache.Builder()
.directory(this.cacheDir.resolve("image_cache"))
.maxSizePercent(0.02)
.build()
}
.build()
and I used like this on splash
val context = LocalContext.current
val request = ImageRequest.Builder(context)
.memoryCacheKey(Constants.Cache.BACKGROUND_IMAGE_KEY)
.data("https://www.example/image1.jpg")
.target(
onSuccess = {
viewModel.skipImageRequest()
},
onError = {
viewModel.skipImageRequest()
}
)
.build()
imageLoader.enqueue(request)
in another screen that I want to use image
#Composable
fun BackgroundImage(
model: Any?,
contentDescription: String? = "",
modifier: Modifier = Modifier.fillMaxSize(),
//placeholder: Painter? = painterResource(R.drawable.bg_placeholder),
error: Painter? = painterResource(R.drawable.bg_placeholder),
fallback: Painter? = painterResource(R.drawable.bg_placeholder),
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.FillBounds
) {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data("https://www.example/image1.jpg")
.placeholderMemoryCacheKey(Constants.Cache.BACKGROUND_IMAGE_KEY)
.build(),
contentDescription = contentDescription,
modifier = modifier,
//placeholder = placeholder,
error = error,
fallback = fallback,
alignment = alignment,
contentScale = contentScale,
)
}
There is an always problem the placeholder image is shown in initialize of page I could not construct a structure where the placeholder is not visible while the image is being loaded and the image is read and used directly from the cahce.
I would be very happy if you support
Coil internally uses OkHttp's DiskCache in 1.x version
For 2.x they have introduced a disk cache to store your result.
For further information read this

How to display video thumbnail in Jetpack Compose?

I'm implementing a simple gallery screen using Jetpack Compose which shows all video and image thumbnails on the screen
I have displayed image from file path successfully. However, I've got trouble in showing video thumbnail. How can I do that using Coil?
Here's my code to show image thumbnails:
#Composable
fun ImageLoaderFromLocal(
url: String,
placeHolderResId: Int,
modifier: Modifier,
transformation: Transformation
) {
val painter = rememberImagePainter(data = File(url),
builder = {
placeholder(placeHolderResId)
crossfade(true)
transformations(transformation)
})
Image(
painter = painter,
contentDescription = null,
modifier = modifier,
contentScale = ContentScale.Inside
)
}
According to Coil documentation, you need to add following dependency:
implementation("io.coil-kt:coil-video:$coil_version")
and specify fetcher in the builder:
val context = LocalContext.current
val painter = rememberImagePainter(
data = url,
builder = {
fetcher(VideoFrameUriFetcher(context))
// optionally set frame location
videoFrameMillis(1000)
placeholder(placeHolderResId)
crossfade(true)
transformations(transformation)
}
)
The other answer doesn't really work any more.
so i tried this one and it worked
val context = LocalContext.current
var visible by rememberSaveable { mutableStateOf(false) }
val imageLoader = ImageLoader.Builder(context)
.components {
add(VideoFrameDecoder.Factory())
}.crossfade(true)
.build()
val painter = rememberAsyncImagePainter(
model = "Your file here",
imageLoader = imageLoader,
The painter should be called in the image composable
like this
Image(
painter = painter,
contentDescription = "",
contentScale = ContentScale.Crop,
alignment = Alignment.Center,
modifier = Modifier.fillMaxSize()
)
i hope this help someone

Loading local drawables with Coil Compose

I recently migrated from Accompanist's ImagePainter to Coil's, below is the pertinent code after my updates.
val painter = rememberImagePainter(DRAWABLE_RESOURCE_ID)
when (painter.state) {
is ImagePainter.State.Empty -> Timber.w("Empty")
is ImagePainter.State.Loading -> {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.wrapContentSize()
) {
CircularProgressIndicator()
}
}
is ImagePainter.State.Success -> {
Image(
painter = painter,
contentDescription = null,
contentScale = ContentScale.Fit,
modifier = Modifier
.padding(8.dp)
.size(84.dp)
.clip(RoundedCornerShape(corner = CornerSize(16.dp)))
)
}
is ImagePainter.State.Error -> Timber.e("Error")
}
Now those images don't render and painter.state is always Empty. My legacy Accompanist implementation displayed images by this point in the code. It also works if I use the stock painterResource(resId) from Compose.
What am I missing to execute Coil's new painter through its states?
As suggested by #Philip Dukhov you don't need coil to load local resources.
If you want to use it, you can simply your code using:
val painter = rememberImagePainter(R.drawable.xxx)
val state = painter.state
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.wrapContentSize()
) {
AnimatedVisibility(visible = (state is ImagePainter.State.Loading)) {
CircularProgressIndicator()
}
Image(
painter = painter,
contentDescription = null,
modifier = Modifier.size(128.dp)
)
}
You can use the drawable's resource ID as model for the coil's AsyncImage composable.
AsyncImage(
model = R.drawable.bg_gradient,
contentDescription = "Gradient background",
)
There's a significant performance difference between the composables - Image and AsyncImage. So Coil's AsyncImage loading is very handy at times.
You don't need coil to load local resources. You can use system painterResource:
Image(
painter = painterResource(id = R.drawable.test),
contentDescription = null,
contentScale = ContentScale.Fit,
modifier = Modifier
.padding(8.dp)
.size(84.dp)
.clip(RoundedCornerShape(corner = CornerSize(16.dp)))
)
If you would use it for remove image loading: since move from accompanist to coil, painter won't start loading unless Image is in the view tree hierarchy. So you can move Image into a Box with your while:
Box(contentAlignment = Alignment.Center) {
val painter = rememberImagePainter(R.drawable.test)
Image(
painter = painter,
contentDescription = null,
contentScale = ContentScale.Fit,
modifier = Modifier
.padding(8.dp)
.size(84.dp)
.clip(RoundedCornerShape(corner = CornerSize(16.dp)))
)
when (painter.state) {
is ImagePainter.State.Empty -> Timber.w("Empty")
is ImagePainter.State.Loading -> {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.wrapContentSize()
) {
CircularProgressIndicator()
}
}
is ImagePainter.State.Success -> {
}
is ImagePainter.State.Error -> Timber.e("Error")
}
}
Also it may not start loading when you're not providing enough size modifiers(that's not your case, just for you to know). Check out this answer for more information.
val context = LocalContext.current
val imageLoader = ImageLoader(context)
val request = ImageRequest.Builder(context)
.data(thumbnailUrl)
.build()
val painter = rememberImagePainter(
request = request,
imageLoader = imageLoader
)
val state = painter.state
Image(
painter = painter,
contentDescription = "thumbnail image",
modifier = Modifier
.fillMaxSize()
.placeholder(
visible = state is ImagePainter.State.Loading,
color = PlaceholderDefaults.color(
backgroundColor = SMXTheme.colors.shimmer.copy(0.1f),
),
highlight = PlaceholderHighlight.shimmer(),
),
contentScale = ContentScale.Crop
)

How to make this custom for Image using Coil

I'm using coil:0.10.0 in my project but it's not as expected, I want to change the image's background
val painter = rememberCoilPainter(
fadeIn = true,
request = ImageRequest.Builder(LocalContext.current)
.data(entry.imageUrl)
.target {
viewModel.calcDominantColor(it) { color ->
dominantColor = color
}
}
.build()
)
Column {
Image(
painter = painter,
contentDescription = entry.pokemonName,
modifier = Modifier
.size(120.dp)
.align(CenterHorizontally)
)
}
}
Expect:
Try Modifier.background(brush = verticalGradient(listOf(dominantColor, Color.White)))

Categories

Resources