tofu
tofu

Reputation: 161

JetPack Compose - weight() in Row in Card doesn't work

When creating an Android app, I put some Composables in a Row of a Card, as shown below, and it did not work as I expected. The Composable that I put "weight(1f)" on was no longer showing up.

data class Test(
    val title: String,
    val text: String
)

@Composable
fun CardRowSample(
    modifier: Modifier = Modifier,
) {
    val testList =
        listOf(
            Test("AAAA", "1,2,3,4,5,6,7,8,9,10"),
            Test("BBBB", "11,12,13,14,15,16,17,18,19,20")
        )

    LazyColumn(
        modifier = modifier
    ) {
         items(
             items = testList
         ) {
             test ->
                Card(
                    elevation = 12.dp,
                    backgroundColor = Color.LightGray,
                    modifier = Modifier
                        .fillMaxWidth()
                        .heightIn(min = 50.dp)
                        .width(40.dp)
                        .requiredHeight(intrinsicSize = IntrinsicSize.Min)
                        .padding(
                            horizontal = 20.dp,
                            vertical = 20.dp
                        )
                        .border(
                            width = 1.dp,
                            color = Color.Black,
                            shape = RectangleShape
                        )
                ) {
                    Row(
                        modifier = Modifier.fillMaxWidth()
                    ) {

                        Icon(
                            modifier = Modifier
                                .padding(horizontal = 5.dp)
                                .align(Alignment.CenterVertically),
                            imageVector = Icons.Filled.Check,
                            contentDescription = null
                        )

                        Text(
                            text = test.title,
                            fontSize = 20.sp,
                            modifier =
                            Modifier
                                .width(120.dp)
                                .padding(horizontal = 10.dp, vertical = 10.dp)
                        )

                        Text(
                            text = test.text,
                            fontSize = 20.sp,
                            modifier = Modifier
                                .weight(1f)//it doesn't work!!
                                .padding(horizontal = 10.dp, vertical = 10.dp)
                        )
                    }
                }
        }
    }
}

enter image description here


My ideal image of the layout:

enter image description here


I wrote the code referring to the following question, Weights in Jetpack compose, but I can't figure out why this is happening. I put "weight" on everything and added fillParentMaxSize to the Row's modifier, but I wasn't able to solve this problem.

What should I do next to solve this problem?

Upvotes: 5

Views: 4026

Answers (2)

Gabriele Mariotti
Gabriele Mariotti

Reputation: 365178

An alternative to the Thracian's answer is to apply Modifier.height(IntrinsicSize.Min) to your Card and fillMaxHeight() to the Icon.

    Card(
        elevation = 12.dp,
        backgroundColor = Color.LightGray,
        modifier = Modifier
            .fillMaxWidth()
            .heightIn(min = 50.dp)
            .height(intrinsicSize = IntrinsicSize.Min)
            .padding(
                horizontal = 20.dp,
                vertical = 20.dp
            )
            .border(
                width = 1.dp,
                color = Color.Black,
                shape = RectangleShape
            )
    ) {
        Row(
            modifier = Modifier.fillMaxWidth()
        ) {

            Icon(
                modifier = Modifier
                    .fillMaxHeight()
                    .padding(horizontal = 5.dp)
                    .align(Alignment.CenterVertically),
                imageVector = Icons.Filled.Check,
                contentDescription = null
            )

            Text(
                text = test.title,
                fontSize = 20.sp,
                modifier =
                Modifier
                    .width(120.dp)
                    .padding(horizontal = 10.dp, vertical = 10.dp)
            )

            Text(
                text = test.text,
                fontSize = 20.sp,
                modifier = Modifier
                    .weight(1f)
                    .padding(horizontal = 10.dp, vertical = 10.dp)
            )
        }
    }
}

enter image description here

Upvotes: 1

Thracian
Thracian

Reputation: 67481

Problem is not with Modifier.weight(1f). It's because of Modifier.requiredHeight(IntrinsicSize.Min)

Card(
    elevation = 12.dp,
    backgroundColor = Color.LightGray,
    modifier = Modifier
        .fillMaxWidth()
        .heightIn(min = 50.dp)
//                    .width(40.dp)
//                    .requiredHeight(intrinsicSize = IntrinsicSize.Min)
        .padding(
            horizontal = 20.dp,
            vertical = 20.dp
        )
        .border(
            width = 1.dp,
            color = Color.Black,
            shape = RectangleShape
        )
) 

Also Modifier.width(40.dp) is redundant because you have another width modifier Modifier.fillMaxWidth() before that.

When Modifier.requiredIn with Intrinsic size modifiers act strange. Composable gets measured twice and with Infinity constraints

LAYOUT constraints: Constraints(minWidth = 0, maxWidth = 1080, minHeight = 0, maxHeight = Infinity), width: 1080, height: 235
LAYOUT constraints: Constraints(minWidth = 0, maxWidth = Infinity, minHeight = 235, maxHeight = 235), width: 510, height: 235

That's the second measurement breaks width because of maxWidth = Infinity. 1080px is full width on my device

to see Constrains and Composable width and height you can use

Card(
    elevation = 12.dp,
    backgroundColor = Color.LightGray,
    modifier = Modifier
        .fillMaxWidth()
        .heightIn(min = 50.dp)
//                    .width(40.dp)
                    .requiredHeight(intrinsicSize = IntrinsicSize.Min)
        .layout { measurable, constraints ->
            val placeable = measurable.measure(constraints)
            println("LAYOUT constraints: $constraints, width: ${placeable.width}, height: ${placeable.height}")
            layout(placeable.width,placeable.height){
                placeable.placeRelative(0,0)
            }
        }
        .padding(
            horizontal = 20.dp,
            vertical = 20.dp
        )
        .border(
            width = 1.dp,
            color = Color.Black,
            shape = RectangleShape
        )
) 

Upvotes: 3

Related Questions