Is there a way to force Jetpack Compose text to be shown?

Viewed 722

So I've been struggling with the following problem for a while. I achieved this (John's example):

What I achieved

But what I'm trying to do is to force the hour to always be shown directly after the text, and if the text is too long - overflow the text. So Jane Doe's example is perfect, same as Jack Doe's (but in Jack's case that's all a dummy text).

And I can't really figure out what I'm doing wrong.

That's the piece of code I wrote:

Row(modifier = Modifier
  .fillMaxWidth()
  .padding(horizontal = 10.dp, vertical = 7.dp),
  verticalAlignment = Alignment.CenterVertically
) {
  Column {
    Row(
      verticalAlignment = Alignment.CenterVertically,
      horizontalArrangement = Arrangement.SpaceBetween
    ) {
      // there's another Row printing the name
    }
    Spacer(Modifier.height(5.dp))
    Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Start) {
      Row(modifier = Modifier.wrapContentWidth(), horizontalArrangement = Arrangement.Start) {
        Text(
          text = item.message,
          style = MaterialTheme.typography.subtitle1,
          maxLines = 1,
          overflow = TextOverflow.Ellipsis
        )
      }
      Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Start) {
        Circle() // that's my function which just shows the circle
        Text(
          text = dateString,
          style = MaterialTheme.typography.subtitle1,
          maxLines = 1,
          modifier = Modifier.padding(horizontal = 4.dp)
        )
      }
    }
  }
}

I'll be really grateful for any kind of help.

2 Answers

Something like this?

@Preview(showBackground = true)
@Composable
fun Test() {
    Column {
        Message(message = "short message")
        Message(message = "short")
        Message(message = "very long message")
    }
}

@Composable
fun Message(message: String) {
    Text("John Doe")
    Row(horizontalArrangement = Arrangement.SpaceBetween) {
        Text(
            message,
            modifier = Modifier.weight(1F, fill = false),
            overflow = TextOverflow.Ellipsis,
            maxLines = 1,
        )
        Text("8:35PM")
    }
}

enter image description here

You can achieve this with a Layout and using IntrinsicWidth. You can build on this example as it only uses 2 Texts for the children, but this should get you on the right path.

@Composable
fun MyRow(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    Layout(
        content = content,
        modifier = modifier,
    ) { measurables, constraints ->
        check(measurables.size == 2) { "This composable requires 2 children" }
        val first = measurables.first()
        val second = measurables[1]

        val looseConstraints = constraints.copy(
            minWidth = 0,
            minHeight = 0,
        )
        val secondMeasurable = second.measure(looseConstraints)
        val maxHeight = secondMeasurable.height
        val availableWidth = constraints.maxWidth - secondMeasurable.width
        val maxWidth = first.maxIntrinsicWidth(maxHeight).coerceAtMost(availableWidth)
        val firstMeasurable = first.measure(
            Constraints(
                minWidth = maxWidth,
                maxWidth = maxWidth,
                minHeight = 0,
                maxHeight = maxHeight
            )
        )
        layout(
            constraints.maxWidth,
            maxHeight,
        ) {
            firstMeasurable.place(0, 0)
            secondMeasurable.place(maxWidth, 0)
        }
    }
}

@Composable
@Preview
fun MyRowPreview() {
    SampleTheme {
        Surface(modifier = Modifier.width(320.dp)) {
            Column(modifier = Modifier.fillMaxWidth()) {
                Text(
                    text = "John Doe",
                    style = MaterialTheme.typography.h5,
                )
                MyRow(modifier = Modifier.fillMaxWidth()) {
                    Text(
                        text = "Short Label",
                        style = MaterialTheme.typography.body1,
                        modifier = Modifier.padding(end = 8.dp),
                        overflow = TextOverflow.Ellipsis,
                        maxLines = 1,
                    )
                    Text(
                        text = "8:35 PM",
                        style = MaterialTheme.typography.body1,
                        modifier = Modifier.padding(start = 8.dp),
                    )
                }
                Spacer(modifier = Modifier.height(16.dp))
                Text(
                    text = "John Doe",
                    style = MaterialTheme.typography.h5,
                )
                MyRow(modifier = Modifier.fillMaxWidth()) {
                    Text(
                        text = "A long label that will require truncation goes here",
                        style = MaterialTheme.typography.body1,
                        modifier = Modifier.padding(end = 8.dp),
                        overflow = TextOverflow.Ellipsis,
                        maxLines = 1,
                    )
                    Text(
                        text = "8:35 PM",
                        style = MaterialTheme.typography.body1,
                        modifier = Modifier.padding(start = 8.dp),
                    )
                }
            }
        }
    }
}

enter image description here

Related