[SOLVED] TextField overflow and softwrap not working with Compose Constraint Layout – Stack Overflow

Issue

This Content is from Stack Overflow. Question asked by David A

I’ve been trying to build a list with a Card in it formatted like this:

Card Content

The difficulty here is that the title e.g. “Bread” and ingredient name e.g. “Flour” can be very long and thus I want to have an ellipsis to keep things manageable i.e. “My Long Flour name” will be displayed as “My Long Flou…” or as much space as is allowed.
The picture size and the gram and percent widths are constant .dp values.

Ellipsis worked fine when it was in a Column but with ConstraintLayout it doesn’t seem to work and I get this:
enter image description here

here’s my code

@Composable
fun BakeItem(
    modifier: Modifier = Modifier,
    bake: Bake,
    cardClicked: () -> Unit,
    ingredeints: List<Ingredient>
) {
    Card(
        modifier = modifier
            .padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp)
            .clickable { cardClicked() }
            .fillMaxSize()
            .wrapContentHeight(),
        border = BorderStroke(4.dp, MaterialTheme.colorScheme.secondary),
        shape = RoundedCornerShape(14.0.dp),
        colors = cardColors(
            containerColor = MaterialTheme.colorScheme.background
        )
    ) {
        val context = LocalContext.current
        val uri = remember(bake.imagePath) { Uri.parse(bake.imagePath) }
        // Card Content

        ConstraintLayout(
            modifier = modifier
                .fillMaxSize()
                .padding(start = 16.dp, top = 8.dp, end = 8.dp, bottom = 8.dp)
        ) {
            val (titleRef, gramColRef, ingrColRef, percentColRef,
                imageRef, dateRef, starsRef) = createRefs()

            Text(
                modifier = modifier
                    .padding(4.dp)
                    .constrainAs(titleRef) {
                        top.linkTo(parent.top, margin = 8.dp)
//                        end.linkTo(imageRef.start, margin = 8.dp)
                        start.linkTo(parent.start, margin = 8.dp)
                    }
                    .background(Color(0xffeeeeee)),
//                textAlign = TextAlign.Left,
                text = if (bake.recipeName.isEmpty()) "<Unnamed>" else bake.recipeName,
                style = MaterialTheme.typography.titleLarge,
                fontWeight = FontWeight.Bold,
                color = MaterialTheme.colorScheme.primary,
                softWrap = false,
                overflow = TextOverflow.Ellipsis,

                )

            Column(
                horizontalAlignment = Alignment.End,
                modifier = modifier
                    .width(50.dp)
                    .constrainAs(gramColRef) {
                        top.linkTo(titleRef.bottom, margin = 8.dp)
                        end.linkTo(ingrColRef.start, margin = 8.dp)
                        start.linkTo(parent.start, margin = 8.dp)
                    }
            ) {
                ingredeints.forEachIndexed { _, it ->
                    Text(
                        text = it.weightGram,
                        style = MaterialTheme.typography.titleSmall,
                        softWrap = false,
                        overflow = TextOverflow.Ellipsis
                    )
                }
            }
            Column(
                modifier = modifier
                    .constrainAs(ingrColRef) {
                        top.linkTo(titleRef.bottom, margin = 8.dp)
                        start.linkTo(gramColRef.end, margin = 8.dp)
                        end.linkTo(ingrColRef.start, margin = 8.dp)
                    },

                ) {
                ingredeints.forEachIndexed { _, it ->
                    Text(
                        text = it.name,
                        style = MaterialTheme.typography.titleSmall,
                        softWrap = false,
                        overflow = TextOverflow.Ellipsis
                    )
                }
            }
            Column(
                modifier = modifier
                    .width(50.dp)
                    .constrainAs(percentColRef) {
                        top.linkTo(titleRef.bottom, margin = 8.dp)
                        end.linkTo(imageRef.start, margin = 8.dp)
                        start.linkTo(ingrColRef.end, margin = 8.dp)
                    },
                horizontalAlignment = Alignment.End
            ) {
                ingredeints.forEachIndexed { i, it ->
                    Text(
                        text = if (i == 0) "" else it.bakingPercent,
                        style = MaterialTheme.typography.titleSmall,
                        softWrap = false,
                        overflow = TextOverflow.Ellipsis
                    )
                }
            }

            Text(
                modifier = modifier.padding(
                    top = 8.dp,
                    start = 4.dp,
                    end = 4.dp,
                    bottom = 4.dp
                ),
                text = bake.notes,
                style = MaterialTheme.typography.titleSmall,
                color = MaterialTheme.colorScheme.onSurface,
                maxLines = 3
            )

            if (bake.imagePath.isNotEmpty()) {
                Image(
                    modifier = modifier
                        .constrainAs(imageRef) {
                            top.linkTo(parent.top, margin = 8.dp)
                            end.linkTo(parent.end, margin = 8.dp)
                        }
                        .padding(4.dp)
                        .requiredSize(150.dp)
                        .clip(RoundedCornerShape(14.dp))
                        .border(
                            4.dp,
                            MaterialTheme.colorScheme.primaryContainer,
                            RoundedCornerShape(14.dp)
                        ),
                    painter = rememberAsyncImagePainter(
                        remember(uri) {
                            ImageRequest.Builder(context)
                                .data(uri)
                                // TODO, think of caching improvements
                                //              .diskCacheKey(uri.toString() + key.value)
                                //              .memoryCacheKey(uri.toString() + key.value)
                                .diskCachePolicy(CachePolicy.DISABLED)
                                .memoryCachePolicy(CachePolicy.DISABLED)
                                .build()
                        }
                    ),
                    contentScale = ContentScale.Crop,
                    contentDescription = "Image of your bake"
                )
            } else {
                Spacer(modifier = modifier
                    .background(Color.Blue)
                    .width(150.dp)
                    .height(10.dp)
                    .constrainAs(imageRef) {
                        top.linkTo(parent.top, margin = 8.dp)
                        end.linkTo(parent.end, margin = 8.dp)
                    })
            }

            Text(
                modifier = modifier
                    .padding(4.dp)
                    .constrainAs(dateRef) {
                        bottom.linkTo(parent.bottom, margin = 8.dp)
                        top.linkTo(imageRef.bottom, margin = 8.dp)
                        end.linkTo(parent.end, margin = 8.dp)
                    },
                text = bake.startTime.toString(),
                style = MaterialTheme.typography.titleMedium,
                color = MaterialTheme.colorScheme.onSurface,
//                    textAlign = Layout.Alignment.ALIGN_CENTER
            )

            createHorizontalChain(
                gramColRef, ingrColRef, percentColRef, imageRef,
                chainStyle = ChainStyle.SpreadInside
            )
            createVerticalChain(
                imageRef, dateRef,
                chainStyle = ChainStyle.SpreadInside
            )
            createHorizontalChain(
                titleRef, imageRef,
                chainStyle = ChainStyle.SpreadInside
            )
        }
    }
}



Solution

In the title you have to add as constrain width = Dimension.fillToConstraints, end.linkTo(imageRef.start, margin = 8.dp) and maxLines = 1:

Text(
    modifier = Modifier
        .padding(4.dp)
        .constrainAs(titleRef) {
            top.linkTo(parent.top, margin = 8.dp)
            end.linkTo(imageRef.start, margin = 8.dp)
            start.linkTo(parent.start, margin = 8.dp)
            width = Dimension.fillToConstraints
        }
        .background(Color(0xffeeeeee)),
    text = "Recipe Name",
    //...
    maxLines = 1,
    overflow = TextOverflow.Ellipsis,
)

For the list instead of using 3 Columns you do can something different.
For the ingredient name add the weight(1f) modifier and the maxLines = 1

        Column(
            modifier = Modifier
                .constrainAs(listRef) {
                    top.linkTo(titleRef.bottom, margin = 8.dp)
                    end.linkTo(imageRef.start, margin = 8.dp)
                    start.linkTo(parent.start, margin = 8.dp)
                    width = Dimension.fillToConstraints
                }
        ) {
            //forEach Row...

            Row(Modifier.fillMaxWidth()) {
                Text(text = "50g", Modifier.width(xx.dp), textAlign = TextAlign.End)

                Text(
                    text = "Very long text long text",
                    Modifier
                        .padding(start=4.dp)
                        .weight(1f),   
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis
                )
                Text(text = "75%", Modifier.width(xx.dp), textAlign = TextAlign.End)
            }
        }

enter image description here


This Question was asked in StackOverflow by David A and Answered by Gabriele Mariotti It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?