How to set the same width and height for a @Composable component in jetpack compose

I have this component:

@Composable
fun CardHome(clickable:()->Unit,text:String,image: Any?){

    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(15.dp)
            .clickable { clickable() },
        elevation = 10.dp
    ) {
        Column(
            modifier = Modifier.padding(10.dp)
        ) {

            AsyncImage(model = image, contentDescription = "${UUID.randomUUID()}", alignment = Alignment.Center, contentScale = ContentScale.Inside)
            Text(text = text, modifier = Modifier.fillMaxWidth().padding(5.dp),
                style= TextStyle(color = Azul2, fontWeight = FontWeight.Bold, fontSize = 15.sp),
                textAlign = TextAlign.Center)
        }
    }
}

But the sizes don't stay the same !! I want all cards of same width and height!!

enter image description here

Upvotes: 0

Views: 4185

Answers (2)

Thracian
Thracian

Reputation: 67268

You can give your Composables same width and height using Modifier.weight(1f).aspectRatio(1f).

This will make sure that, if your Composables are inside a row, share available space of parent evenly and using this width set aspectRatio to set height either. I made a sample for demonstration

I changed your card as

@Composable
fun CardHome(
    modifier: Modifier,
    clickable: () -> Unit,
    text: String,
    image: Any?
) {

    Card(
        modifier = modifier,
        onClick = clickable
    ) {
        Column(
            modifier = Modifier.padding(10.dp)
        ) {

            AsyncImage(
                modifier = Modifier
                    .fillMaxWidth()
                    .weight(1f),
                model = image,
                contentDescription = "${UUID.randomUUID()}",
                alignment = Alignment.Center,
                contentScale = ContentScale.Inside
            )
            Text(
                text = text, modifier = Modifier
                    .fillMaxWidth()
                    .padding(5.dp),
                textAlign = TextAlign.Center
            )
        }
    }
}

Added weight for image to cover available space that is not used by Text

And placed them inside a Row using Modifier.weight(1f).aspectRatio(1f)

Row(
    modifier = Modifier
        .fillMaxWidth()
        .padding(10.dp)
) {
    CardHome(
        modifier = Modifier
            .weight(1f)
            .aspectRatio(1f),
        clickable = { /*TODO*/ },
        text = "Hello World",
        image = R.drawable.landscape1
    )

    Spacer(modifier = Modifier.width(10.dp))
    CardHome(
        modifier = Modifier
            .weight(1f)
            .aspectRatio(1f),
        clickable = { /*TODO*/ },
        text = "Hello World",
        image = R.drawable.landscape2
    )
}

Image draw area is not even because of ContentScale.Center

enter image description here

Upvotes: 2

I have the solution adding some modifier props to AsyncImge:

@Composable
fun CardHome(clickable:()->Unit,text:String,image: Any?){

    Card(
        modifier = Modifier
            .fillMaxWidth()

            .padding(15.dp)
            .clickable { clickable() },
        elevation = 10.dp
    ) {
        Column(
            modifier = Modifier.padding(10.dp)
        ) {

            AsyncImage(modifier = Modifier.fillMaxWidth().heightIn(min = 100.dp), model = image,
                contentDescription = "${UUID.randomUUID()}",
                alignment = Alignment.Center, contentScale = ContentScale.FillBounds)
            Text(text = text, modifier = Modifier.fillMaxWidth().padding(5.dp),
                style= TextStyle(color = Azul2, fontWeight = FontWeight.Bold, fontSize = 15.sp),
                textAlign = TextAlign.Center)
        }
    }
}

Upvotes: 0

Related Questions