How to load local image using Jetpack compose - android

I'm using android's photo-picker and then dumping the path into a DB. That all works, but when I try to load the image from RoomDB the image does not load.
I've tried using Image and AsyncImage, but no luck. I've also converted the string to .toUri()
val painter = rememberImagePainter(data = File("content://media/picker/0/com.android.providers.media.photopicker/media/1000000020"))
Image( painter = painter, contentDescription = null)
AsyncImage(model = "content://media/picker/0/com.android.providers.media.photopicker/media/1000000020",
contentDescription = "Image from photo picker",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(100.dp, 100.dp)
)

Related

How can i parse Uri String for loading image from gallery in jetpack compose with Coil?

Let say i have image components can show image from selected image from gallery;
#Composable
fun ClickableToGalleryImage() {
var imageUri by remember {
mutableStateOf<Uri?>(null)
}
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.GetContent()
) { uri: Uri? ->
println(imageUri)
imageUri = uri
}
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Image(
painter = rememberAsyncImagePainter(
ImageRequest
.Builder(LocalContext.current)
.data(data = imageUri)
.build()
),
contentDescription = null,
modifier = Modifier
.clickable { launcher.launch("image/*") }
.size(100.dp)
.clip(CircleShape)
.border(2.dp, Color.Gray, CircleShape),
contentScale = ContentScale.Crop
)
}
}
this works very well.
But if i extract the imageUri value;
I/System.out: content://com.android.providers.media.documents/document/image%3A33
and manually type the imageUri variable;
Image(
painter = rememberAsyncImagePainter(
ImageRequest
.Builder(LocalContext.current)
.data(data = "content://com.android.providers.media.documents/document/image%3A33")
.build()
),
contentDescription = null,
modifier = Modifier
.size(100.dp)
.clip(CircleShape)
.border(2.dp, Color.Gray, CircleShape),
contentScale = ContentScale.Crop
)
Coil can't load picture. Why is that? And how can i show picture from gallery with uri?
Coil can't load picture. Why is that?
You do not have read permission to access the content.
And how can i show picture from gallery with uri?
Use the Uri that you get back from your ActivityResultContracts.GetContent request, in the same activity where you requested it.
If you need durable access to the content, switch to OpenDocument and call takePersistableUriPermission() on a ContentResolver, supplying the Uri.

How to modify color and size for Coil image placeholder in Jetpack Compose

I'm using Coil 1.3.2 in Jetpack Compose and I have an Image like this
Image(
painter = rememberImagePainter(
data = imageUrl,
onExecute = { _, _ -> true },
builder = {
placeholder(R.drawable.icon)
}
),
contentScale = ContentScale.FillWidth,
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1f)
)
How can I set a custom color and size for my placeholder icon ?
I didn't find any examples on the documentation
You can use painter.state to see if the image is still loading, and use Box to display the desired placeholder. Note that the Image to be loaded must be in the view hierarchy, just defining rememberImagePainter won't start loading.
You can use either Image or Icon for the placeholder: if you need to change tint color, the second option seems cleaner:
Box(contentAlignment = Alignment.Center) {
val painter = rememberImagePainter(data = imageUrl)
Image(
painter = painter,
contentScale = ContentScale.FillWidth,
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1f)
)
if (painter.state !is ImagePainter.State.Success) {
Icon(
painter = painterResource(id = R.drawable.icon),
contentDescription = null,
tint = Color.Blue,
modifier = Modifier.size(100.dp)
)
}
}
I'm using contentAlignment = Alignment.Center to center static size placeholder inside the Box, also you can add Modifier.matchParentSize() to the placeholder so it'll be the same size as the image, use fillMaxSize(part) to take part of parent space, etc.
Also you can use AnimatedVisibility instead of if to add an animation.
AFAIK you cannot do that using the resource directly, but you could use different placeholder overload taking the Drawable object. You could try and do what you need directly in that object

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

How to load Image Files into Jetpack Compose Image using Coil

I would like to load saved image on cache into Image of Jetpack Compose using Coil. I searched in stackoverflow but all suggested ways are for loading web urls. I know that It's possible to convert image file to bitmap and then pass it to Coil but is there any builtin solution for it?
You can use Coil to load any object as a data:
val cacheFile = File(context.cacheDir, "filename")
Image(
rememberImagePainter(cacheFile),
contentDescription = "...",
)
If you've a locally saved image path, you can try the following method,
val painter = rememberImagePainter(data = File(filePath))
Image(
painter = painter,
contentDescription = null)
and to load image from remote url,
val painter = rememberImagePainter(data = imageUrl)
Image(
painter = painter,
contentDescription = null)
For the new version of coil 2.2.2, rememberImagePainter didn't give me good results so I used this-
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(<file_path>)
.build(),
contentDescription = "icon",
contentScale = ContentScale.Inside,
modifier = Modifier.size(30.dp)
)
Hope it helps 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
)

Categories

Resources