Есть ли способ заставить Jetpack выводить текст для отображения?

#android #android-jetpack-compose

Вопрос:

Поэтому я некоторое время боролся со следующей проблемой. Я добился этого (пример Джона).:

Чего я добился

Но то, что я пытаюсь сделать, — это заставить час всегда отображаться непосредственно после текста, а если текст слишком длинный- переполнить текст. Так что пример Джейн Доу идеален, как и пример Джека Доу (но в случае Джека это всего лишь фиктивный текст).

И я действительно не могу понять, что я делаю не так.

Это тот фрагмент кода, который я написал:

 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)
        )
      }
    }
  }
}
 

Я буду очень благодарен за любую помощь.

Комментарии:

1. Такое ощущение, что у вас должен быть один Row() с Text() , Circle() , и Text() , используя модификаторы, чтобы придать второму Text() его естественную ширину и предоставить все лишнее пространство первому Text() .

2. @CommonsWare спасибо за этот ответ — действительно, я превратил эти две строки в одну, но все еще не могу понять, как сделать вторую часть. Я пытался использовать Modifier.wrapContentWidth() для второго текста, но все равно похоже, что первый текст создается первым и, таким образом, занимает все доступное пространство. Не могли бы вы, пожалуйста, приложить пример того, как это должно выглядеть?

Ответ №1:

Что-то вроде этого?

 @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")
    }
}
 

введите описание изображения здесь

Комментарии:

1. Я пробовал что-то подобное (с maxLines = 1 параметром в первом Text() ). Хотя он отлично работает, когда текст длинный (длиннее ширины строки), он всегда показывает время в конце строки, даже если первый Text() очень короткий, и это не совсем то, чего я ожидал. Но все равно спасибо за ответ

2. Не могли бы вы помочь мне понять, чего он хочет? У вас есть скриншот или макет?

3. Таким образом, основные предположения были следующими: 1. Первый текст (сообщение) всегда имеет длину не более 1 строки 2. Если сообщение длиннее 1 строки — оно переполнено (используется многоточие), и в конце строки отображается час 3. Если сообщение короче 1 строки, оно отображается полностью, и час отображается сразу после окончания сообщения. Но ответ, предоставленный @Francesc, охватывал все эти 3 пункта

4. Хорошо, я думаю, что понимаю это немного лучше.. Я обновил свой ответ

5. Вау, похоже, этот fill = false аргумент работает идеально. Большое спасибо!

Ответ №2:

Вы можете достичь этого с Layout помощью и с помощью IntrinsicWidth . Вы можете опираться на этот пример, так как он использует только 2 Text секунды для детей, но это должно вывести вас на правильный путь.

 @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),
                    )
                }
            }
        }
    }
}
 

введите описание изображения здесь

Комментарии:

1. Вау, я действительно надеялся, что есть более простой способ, хотя он отлично сработал, так что большое спасибо!