I want to show picture with Coil from Uri.
Following code shows picture but when I choose one.
I want to store Uri and when Screen starts i want to show it immediately.
val uri = "content://com.android.providers.media.documents/document/image%3A18".toUri()
var imageUri by remember { mutableStateOf<Uri?>(null) }
val context = LocalContext.current
val launcher =
rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent()) {
uri: Uri? ->
imageUri = uri
}
Column {
Button(onClick = {
//here we are going to add logic for picking image
launcher.launch(
"image/*"
)
}, content = {
Text(text = "Select Image From Gallery")
})
AsyncImage(
model = ImageRequest.Builder(context = context)
.data(imageUri)
.crossfade(true)
.build(),
contentDescription = "",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(144.dp)
)
Image(
painter = rememberAsyncImagePainter(imageUri),
contentDescription = "Picture",
)
val uri is uri I chooshed before and I copied it and put to string to show image.
But this way first I need to choose picture and it will show. If I put uri instead of imageUri in .data() or rememberAsyncImagePainter nothing happens.
Related
I'm trying to fetch image uri and then display it in my application with coil.
var imageUri by remember { mutableStateOf<Uri?>(null) }
val launcher =
rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent()) { uri: Uri? ->
imageUri = uri
}
Column {
Button(onClick = {
//here we are going to add logic for picking image
launcher.launch(
"image/*"
)
}, content = {
Text(text = "Select Image From Gallery")
})
Log.d(TAG, "ClientCardItem: $imageUri")
Text(text = imageUri.toString())
I made this just to check if i fetched uri. I got result like this:
"content://com.android.providers.media.documents/document/image%3A18", i put it to string.
This is for image display:
Image(
painter = rememberImagePainter(
data = Uri.parse(uri) // or ht
)
,
contentDescription = "123",
modifier = Modifier.height(200.dp).width(200.dp),
contentScale = ContentScale.FillWidth
)
I know that I dont have .jpg or .png or something else to display it properly. My question is how to get that format to display picture I picked.
EDIT:
rememberAsyncImagePainter, rememberImagePainter or AsyncImage are not found ?
After I updated to:
implementation "io.coil-kt:coil:2.2.2"
On AsyncImage() -> Unresolved reference: AsyncImage
To display the image just use:
AsyncImage(model = imageUri, contentDescription = "Picture")
or:
Image(
painter = rememberAsyncImagePainter(imageUri),
contentDescription = "Picture",
)
In my view model I have:
var uri = savedStateHandle.getStateFlow("uri", Uri.EMPTY)
private set
In my view:
val uri by viewModel.uri.collectAsState()
Image(
painter = rememberAsyncImagePainter(
ImageRequest
.Builder(LocalContext.current)
.data(data = uri)
.build()
),
contentDescription = "",
modifier = Modifier
.padding(vertical = 16.dp)
.size(avatarSize.value)
.clip(CircleShape)
,
contentScale = ContentScale.Crop
)
When I am saving new image it is saved with the same uri in local strage so my Image is not recomposed and old one is presented.
I can change uri and then image is recomposed as intended but how to inform my Image that it should be recomposed even when uri is still the same?
You can use coil's setParameter method on the builder which will reload whenever the parameter changes. You can use timestamp of last change as a parameter or something like that.
val timestamp by viewModel.timestamp.collectAsState()
ImageRequest
.Builder(LocalContext.current)
.data(data = uri)
.setParameter("timestamp", timestamp, null)
.build()
Hey I'm new to kotlin and I'm having problem with this. The images are in the drawable folder. And I need to share the image in jetpack composer. When I click now I can only see the text but not the image to share.
Image(
painter = painterResource(id = image.imgId),
contentDescription = "Test",
modifier = Modifier.fillMaxWidth()
)
var pickedImageUri by remember { mutableStateOf<Uri?>(null) }
val context = LocalContext.current
val intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, pickedImageUri)
putExtra(Intent.EXTRA_TEXT, "Description of Image")
type = "image/*"
}
val shareIntent = Intent.createChooser(intent, "Share")
Button( onClick = {
//val description = "Image sent"
context.startActivity(shareIntent)
}) {
Text("Share")
}
I am looking for help on how to share image binary content from my PhotoApp to external Social Media apps.
I load the image from an API using Coil and display the image in a composable.
#Composable
fun PhotoDetailsScreen( photo: AstroPhoto ... ) {
val context = LocalContext.current
val imgUri = photo.url.toUri()
.buildUpon()
.scheme("https")
.build()
Column ( ...
//Image
Image(
painter = rememberImagePainter(
data = imgUri,
builder = {
crossfade(true)
placeholder(R.drawable.loading_animation)
}
) ...
//Assist Chip
AssistChip(onClick = { shareAstroPhoto("", context) }
Clicking on the AssistChip calls the below shareAstroPhoto() fxn that takes the uri pointing to the image file to fire an ACTION_SEND Intent
fun shareAstroPhoto(uri:String, context: Context){
val intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, uri)
type = "image/jpg"
}
context.startActivity(Intent.createChooser(intent, null))
}
I intend to get a Bitmap out of my composable, save the Bitmap in my own ContentProvider or MediaStore (I know how these 2 work) and then pass the uri of the saved BitMap to Intent.EXTRA_STREAM.
Have browsed through similar cases and videos but all I find is working with XML code.
Therefore my query is how to convert Jetpack Compose Image from a composable into a Bitmap to enable sharing the file with other external apps through Android Sharesheet.
I'm not sure if I understand your question. If you just want to share the image, then:
Util function:
fun Context.shareImage(title: String, image: Drawable, filename: String) {
val file = try {
val outputFile = File(cacheDir, "$filename.png")
val outPutStream = FileOutputStream(outputFile)
image.toBitmap().compress(CompressFormat.PNG, 100, outPutStream)
outPutStream.flush()
outPutStream.close()
outputFile
} catch (e: Throwable) {
return toast(e)
}
val uri = file.toUriCompat(this)
val shareIntent = Intent().apply {
action = Intent.ACTION_SEND
type = "image/png"
putExtra(Intent.EXTRA_STREAM, uri)
}
startActivity(Intent.createChooser(shareIntent, title))
}
Share image with (Coil 2.0):
val painter = rememberAsyncImagePainter(
ImageRequest.Builder(LocalContext.current)
.data(url)
.build()
)
Button(
onClick={
val state = painter.state as? AsyncImagePainter.State.Success
val drawable = state?.result.drawable
context.shareImage(
"Share image via",
drawable,
"filename"
)
}
)
Updated
Those are small helper functions, but if you want them:
fun File.toUriCompat(context: Context): Uri {
return FileProvider.getUriForFile(context, context.packageName + ".provider", this)
}
fun Context.toast(throwable: Throwable) =
throwable.message?.let { toast(it) }
?: toast(R.string.unknown_error)
fun Context.toast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
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
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.