Mr. Techie
Mr. Techie

Reputation: 886

Make composable wrap content - Jetpack Compose

I am trying to make the ImageComposable wrap its height and width according to its content, along with the two Text composable, align to the bottom of Assemble composable. Following is the code for that:

@Composable
fun ImageComposable(url:String){
    val painter = rememberAsyncImagePainter(
        model = ImageRequest.Builder(LocalContext.current).data(url).apply{
            placeholder(drawableResId = R.drawable.ic_broken_pic)
        }.build()
    )
    Image(painter = painter, contentDescription = null, Modifier.padding(2.dp).border(width = 2.dp, shape = CircleShape, color = MaterialTheme.colors.onPrimary)

}

@Composable
fun Assemble(url:String){
    Column (modifier = Modifier.fillMaxWidth().height(400.dp).background(MaterialTheme.colors.primary)
        .padding(16.dp), verticalArrangement = Arrangement.Bottom) {
        ImageComposable(url)
        Text(text = "title")
        Text(text = "Body")
    }
}

but the ImageComposable ends up taking all the height and width of the Assemble composable and I am not able to see the two Text composables that I added in the column. So I am confused as to what is the exact problem here. I thought at least it should show the ImageComposable along with the two Text composable but it is not happening.

I am using coil image loading library here for parsing the image from url. For now in testing, I am passing url as an Empty String. Hence I am calling the composable as:
Assemble("")

I didn't find any document that would help me understand this behavior. So I wanted to know the reason to this problem and possible solutions to overcome it.

Upvotes: 1

Views: 8872

Answers (2)

KraffMann
KraffMann

Reputation: 352

It would be easier to solve your problem if there would be a sketch of what you want to achieve.

Nevertheless, I hope I can help: It looks like the issue you are facing can be handled by Intrinsic measurements in Compose layouts.

The column measures each child individually without the dimension of your text constraining the image size. For this Intrinsics can be used.

Intrinsics lets you query children before they're actually measured.

For example, if you ask the minIntrinsicHeight of a Text with infinite width, it'll return the height of the Text as if the text was drawn in a single line.

By using IntrinsicSize.Max for the width of the Assemble composable like this:

@Composable
fun Assemble(url: String) {
    Column(
        modifier = Modifier
            .width(IntrinsicSize.Max)
            .background(MaterialTheme.colors.primary)
            .padding(16.dp), verticalArrangement = Arrangement.Bottom
    ) {
        ImageComposable(url)
        Text(text = "title")
        Text(text = "Body")
    }
}

you can can create a layout like this:

Preview Assemble Composable

(Please note that I am using a local drawable here)

You can now see the 2 texts and the width of the image is adjusted to the width of the texts.

Using Intrinsics to measure children in dependance to each other should help you to achieve what you wanted.

Please let me know if this layout does not meet your expectations.

Upvotes: 1

bylazy
bylazy

Reputation: 1305

You can explicitly specify the height of each component:

fun ImageComposable(modifier: Modifier = Modifier, url: String){
//...
    Image(modifier = modifier, //...
}

Column(//..
   ImageComposable(modifier = Modifier.height(200.dp)//...
   Text(modifier = Modifier.height(50.dp)//...
   Text(modifier = Modifier.height(150.dp)//...
}

Or you can specify a fraction of the maximum height it will take up:

fun ImageComposable(modifier: Modifier = Modifier, url: String){
//...
    Image(modifier = modifier, //...
}

Column(//..
   ImageComposable(modifier = Modifier.fillMaxHeight(0.75f)//...
   Text(modifier = Modifier.fillMaxHeight(0.1f)//...
   Text(modifier = Modifier.fillMaxHeight(0.15f)//...
}

You can also try playing with the weight modifier:

fun ImageComposable(modifier: Modifier = Modifier, url: String){
//...
    Image(modifier = modifier, //...
}

Column(//..
   ImageComposable(modifier = Modifier.weight(1f)//...
   Text(modifier = Modifier.weight(1f, fill = false)//...
   Text(modifier = Modifier.weight(1f, fill = false)//...
}

Upvotes: -1

Related Questions