androiduser-interfaceandroid-jetpack-composeconstraintsandroid-jetpack-compose-material3

LazyColumn and Constraint in JetPack Compose


I am setting up a list based design using jetpack compose + constraint in that but I am facing some issue with the constraint link as it won't work properly when it is linked to parent.

Here is my code

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ProductCard(product:ProductModel){
    ElevatedCard(
        onClick = { },
        modifier = Modifier
            .padding(start = 15.dp, end = 15.dp, top = 10.dp, bottom = 10.dp)
            .fillMaxWidth(),
        colors = CardDefaults.cardColors(
            containerColor = Color.White,
        )
    ) {
        ConstraintLayout{
            val (productImage,productName,productCategory,
                productPrice,ratingPrice) = createRefs()

            AsyncImage(
                model = ImageRequest.Builder(LocalContext.current)
                    .data(product.productImage)
                    .crossfade(true)
                    .build(),
                contentDescription = null,
                placeholder = painterResource(id = R.drawable.user),
                contentScale = ContentScale.Crop,
                modifier = Modifier
                    .constrainAs(productImage) {
                        start.linkTo(parent.start, margin = 10.dp)
                        top.linkTo(parent.top, margin = 15.dp)
                        end.linkTo(productName.start)
                        bottom.linkTo(parent.bottom)
                    }
                    .width(72.dp)
                    .height(72.dp)
            )

            Text(
                modifier = Modifier
                    .constrainAs(productName) {
                        top.linkTo(productImage.top)
                        start.linkTo(productImage.end, margin = 10.dp)
                        end.linkTo(parent.end,margin = 10.dp)
                        width = Dimension.wrapContent
                    },
                text = product.productName,
                fontFamily = notoSansFontFamily,
                fontWeight = FontWeight.Bold,
                fontSize = 16.sp,
            )

            Text(
                modifier = Modifier
                    .constrainAs(productCategory) {
                        top.linkTo(productName.bottom, margin = 5.dp)
                        start.linkTo(productName.start)
                        width = Dimension.wrapContent
                    },
                text = product.productCategory,
                fontFamily = notoSansFontFamily,
                fontWeight = FontWeight.Medium,
                fontSize = 15.sp,
            )

            Row(
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.SpaceBetween,
                modifier = Modifier.constrainAs(ratingPrice){
                    top.linkTo(productCategory.bottom, margin = 5.dp)
                    start.linkTo(productName.start)
                    end.linkTo(parent.end)
                    width = Dimension.fillToConstraints
                }
                    .background(Color.Blue)
            ) {
                Text(
                    text = product.productPrice,
                    fontFamily = notoSansFontFamily,
                    fontWeight = FontWeight.Bold,
                    fontSize = 14.sp,
                    color = Color.White
                )

                Text(
                    text = "Rating : ${product.productRating}",
                    fontFamily = notoSansFontFamily,
                    fontWeight = FontWeight.Normal,
                    fontSize = 12.sp,
                    color = Color.Yellow,
                    modifier = Modifier.background(Color.Red)
                )
            }

Inside Row I updated the code added up the arrangement, the result is different for all the cards. It is very straight Row should be linkTo startOf productName and endOf parent. Don't know why it us behaving different for each card. Check out the image, it is rendering same in physical and emulator device.

Lazy Column


Solution

  • Please try to add the horizontalArrangement parameter to the Row and make sure the ConstraintLayout uses fillMaxWidth():

    ConstraintLayout(
        modifier = Modifier.fillMaxWidth()  // add this line
    ) {
    
        //...
    
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.SpaceBetween,  // add this line
            modifier = Modifier.constrainAs(ratingPrice){
                top.linkTo(productCategory.bottom, margin = 5.dp)
                start.linkTo(productName.start)
                end.linkTo(parent.end)
                width = Dimension.fillToConstraints
            }
                .background(Color.Blue)
        ) {
            //...
        }
    }
    

    You will also have to change your productName and productCategory Composables. You can make sure the text aligns to the left by using a combination like this:

    Text(
         modifier = Modifier
             .constrainAs(productName) {
                 //...
                 width = Dimension.fillToConstraints
             }
             //...
         ,
         textAlign = TextAlign.Start,
         //...
    }