Jetpack Compose Coil Preload - android

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

Related

AsyncImage in LazyColumn Kotlin Compose

I have a list of photos from the internet and I want to load them into a LazyColumn. The problem is that some of them are loading faster than others so the photos appear in random order.
Here is the code:
val state = viewModel.photos.collectAsState()
val lastIndex = state.value.lastIndex
LazyColumn {
itemsIndexed(state.value) { i, photo ->
AsyncImage(
model = photo.urls.regular,
contentDescription = null,
modifier = Modifier.fillMaxWidth(),
)
if (i >= lastIndex-1 && !viewModel.isLoading.value) {
viewModel.getPhotos(6)
}
}
}
Sometimes image with LastIndex-1 occurs first and it triggers viewModel to get new data.
How can I make a handler for loading a list of images? Or maybe any suggestions on how to make a preloading screen which will end after loading all images into LazyColumn
I also have a Coil version too:
val model = ImageRequest.Builder(LocalContext.current)
.data(photo.urls.regular)
.size(Size.ORIGINAL)
.crossfade(true)
.build()
val painter = rememberAsyncImagePainter(model)
Image(
painter = painter,
contentDescription = null,
modifier = Modifier.fillMaxWidth(),
)

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(),
//
)

Convert a composable view into image in Jetpack Compose

I have a composable for example
Box(modifier){ ... }
I want to share this view as an image with other apps, that's why I have to convert this Box into an image that can be shared with other apps such as WhatsApp etc. Thank you
You can check out this link for how to build your own capturing system
How to screenshot selectively or scrollable Composable?
You basically get view using
val view: View = LocalView.current
then get position of your Composable using
var composableBounds by remember {
mutableStateOf<Rect?>(null)
}
using onGloballyPositionedModifier
Box(modifier = modifier
.onGloballyPositioned {
composableBounds = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
it.boundsInWindow()
} else {
it.boundsInRoot()
}
}
) {
content()
}
Then capturing image using
val bitmap = Bitmap.createBitmap(
width,
height,
Bitmap.Config.ARGB_8888
)
PixelCopy, this is important, if you don't use this on Oreo and above you are likely to get crash on some devices
PixelCopy.request(
(this.context as Activity).window,
bounds.toAndroidRect(),
bitmap)
or
val canvas = Canvas(bitmap)
.apply {
translate(-bounds.left, -bounds.top)
}
this.draw(canvas)
canvas.setBitmap(null)
bitmapCallback.invoke(ImageResult.Success(bitmap))
i also created a library that takes screenshot or screenshots in specified interval.
https://github.com/SmartToolFactory/Compose-Screenshot
Problem with mine and every other screen capture library out there is not being able to capture scrollable Composables by default.
Box(
modifier: BoxModifier(
shape: BoxShape.rectangle,
color: Colors.red,
),
child: Image.network(
'https://picsum.photos/250?image=9',
),
);
This code converts the Box into an image that can be shared with other apps. The BoxModifier class provides a way to modify the appearance of a box, and the Image class provides a way to display images.
You can get drawable using painter in jetpack compose, then use that Drawble to share..
#Composable
fun photoItem(
photoUrl: String,
modifier: Modifier = Modifier,
contentScale: ContentScale = ContentScale.Fit
): Drawable? {
val painter = rememberAsyncImagePainter(
Builder(LocalContext.current)
.placeholder(drawable.placeholder)
.data(photoUrl)
.build()
)
Image(
contentScale = contentScale,
painter = painter,
contentDescription = null,
modifier = modifier,
)
val state = painter.state as? AsyncImagePainter.State.Success
return state?.result?.drawable
}
then cast the Drawable to BitmapDrawable

How to use `ImageRequest.Builder.target` in the new coil version in jetpack compose?

My Gradle
// Coil
implementation "io.coil-kt:coil-compose:1.4.0"
Problem Description
Previously I used the coil together with Google's accompanist, but when I migrate to the new version of the coil as the documentation suggests I'm having problems with the target method:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.pokedex, PID: 13502
java.lang.IllegalArgumentException: request.target must be null.
at coil.compose.ImagePainterKt.rememberImagePainter(ImagePainter.kt:94)
...
Coil Implementation
When browsing the internal code of ImagePainter (coil class) you can see that the target method really needs to be null for some reason:
#Composable
fun rememberImagePainter(
request: ImageRequest,
imageLoader: ImageLoader,
onExecute: ExecuteCallback = ExecuteCallback.Default,
): ImagePainter {
requireSupportedData(request.data)
require(request.target == null) { "request.target must be null." }
...
My Code
Here's my component in jetpack compose (the image component is inside a column):
Image(
modifier = Modifier
.size(120.dp)
.align(Alignment.CenterHorizontally),
painter = rememberImagePainter(
data = entry.imageUrl,
builder = {
crossfade(true)
target {
viewModel.calcDominantColor(it) { color ->
dominantColor = color
}
}
transformations(CircleCropTransformation())
},
),
contentDescription = entry.pokemonName
)
I need the target method to do internal operations on my viewModel based on the drawable it passes as a parameter. Can someone help me?
In Coil 2.0.0 both AsyncImage and rememberAsyncImagePainter have onSuccess callback parameter, using which you can get the drawable as follows:
AsyncImage(
model = imageURL,
contentDescription = null,
onSuccess = { success ->
val drawable = success.result.drawable
}
)
Coil 1.4.0 version:
This is intended behaviour since rememberImagePainter sets the target internally.
You can track the painter state, wait for the Success and get the drawable from it. Also use it with LaunchedEffect to prevent re-calculations:
val painter = rememberImagePainter(
data = imageUrl,
builder = {
...
},
)
(painter.state as? ImagePainter.State.Success)
?.let { successState ->
LaunchedEffect(Unit) {
val drawable = successState.result.drawable
viewModel.calcDominantColor(drawable) { color ->
dominantColor = color
}
}
}
Image(
painter = painter,
contentDescription = "...",
modifier = Modifier
...
)
I know you follow this https://www.youtube.com/watch?v=jrIfGAk8PyQ&list=PLQkwcJG4YTCTimTCpEL5FZgaWdIZQuB7m&index=5
by Philipp Lackner
try this code
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(entry.imageUrl)
.crossfade(true)
.build(),
contentDescription = entry.pokemonName,
onSuccess = {
viewModel.calcDominantColor(it.result.drawable) { color ->
dominantColor = color
}
},
modifier = Modifier
.size(120.dp)
.align(CenterHorizontally)
)
and use this library implementation("io.coil-kt:coil-compose:2.2.2")
and to more information https://coil-kt.github.io/coil/compose/

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

Categories

Resources