Преобразование макета ограничений XML в Jetpack Compose — стиль цепочки, смещение

Я пытаюсь создать конкретный макет с двумя представлениями: TextView и ImageView. TextView является динамическим, то есть длина текста может варьироваться. Если длина текста меньше ширины устройства, ImageView должен быть выровнен по концу TextView. Однако если длина текста превышает ширину устройства, ImageView должен располагаться в конце ширины устройства. Текст может занимать несколько строк, в зависимости от содержимого.

Я только начинаю работать с Jetpack Compose и создал макет, используя ConstraintLayout XML. Я пытаюсь преобразовать этот макет в Jetpack Compose, но не уверен насчет эквивалентных методов для layout_constraintHorizontal_bias, layout_constraintHorizontal_chainStyle и layout_constrainedWidth в Jetpack Compose.

Вот полный XML-код, с которым я работаю:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    android:layout_width = "match_parent"
    android:layout_height = "wrap_content"
    xmlns:app = "http://schemas.android.com/apk/res-auto">

    <TextView
        android:id = "@+id/textview"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        app:layout_constrainedWidth = "true"
        app:layout_constraintHorizontal_bias = "0"
        app:layout_constraintHorizontal_chainStyle = "packed"
        app:layout_constraintTop_toTopOf = "parent"
        app:layout_constraintEnd_toStartOf = "@+id/image"
        android:text = "lorem epsum loremsum loremlorem epsum loremsum loremlorem epsum loremsum loremlorem epsum loremsum loremlorem epsum loremsum lorem"
        app:layout_constraintStart_toStartOf = "parent"/>
    <ImageView
        android:id = "@+id/image"
        android:layout_width = "14dp"
        android:layout_height = "14dp"
        app:layout_constraintEnd_toEndOf = "parent"
        app:layout_constraintTop_toTopOf = "@id/textview"
        app:layout_constraintBottom_toBottomOf = "@id/textview"
        app:layout_constraintStart_toEndOf = "@+id/textview"
        android:src = "@drawable/ic_information_grey"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Я попробовал:

@Composable
fun CustomLayout(inputText: String) {
    ConstraintLayout(modifier = Modifier.fillMaxWidth()) {
    val (text, image) = createRefs()

    val chain = createHorizontalChain(text,image, chainStyle = ChainStyle.Packed(0F))
    constrain(chain){
        start.linkTo(text.start)
        end.linkTo(image.end)
    }
    Text(
        text = inputText,
        modifier = Modifier
            .constrainAs(text) {
                start.linkTo(parent.start)
                end.linkTo(image.start)
                top.linkTo(parent.top)
                width = Dimension.preferredWrapContent
            }.wrapContentSize()
    )

    Image(
        painter = painterResource(id = R.drawable.ic_information_grey),
        contentDescription = null,
        modifier = Modifier
            .size(14.dp)
            .constrainAs(image) {
                end.linkTo(parent.end)
                top.linkTo(text.top)
                start.linkTo(text.end)
                width = Dimension.wrapContent
            }.wrapContentSize()
    )
}
}

Есть ли причина, по которой вам нужно придерживаться макета с ограничениями вместо использования стандартных компонентов макета, таких как Row?

Ricky Mo 26.04.2024 07:57

Обновил свой вопрос, мне не удалось добиться такого же поведения с помощью Row.

Bincy Baby 26.04.2024 08:25
2
2
124
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

После нескольких попыток я нашел решение. Моя ошибка заключалась в вызове createHorizontalChain перед установкой ограничений. Теперь я переместил функцию createHorizontalChain в конец после определения компонентов Text и Image. Это связано с тем, что функцию createHorizontalChain следует вызывать после определения компонентов и установки их ограничений.

ConstraintLayout(modifier = Modifier.fillMaxWidth().padding(top = 5.dp, start = 10.dp, bottom = 10.dp, end = 5.dp)) {
        val (text, image) = createRefs()

        Text(
            text = description.toString(),
            modifier = Modifier
                .constrainAs(text) {
                    start.linkTo(parent.start)
                    width = Dimension.preferredWrapContent
                }
                .wrapContentSize()
        )

        Image(
            painter = painterResource(id = R.drawable.ic_information_grey),
            contentDescription = null,
            modifier = Modifier
                .size(14.dp)
                .constrainAs(image) {
                    start.linkTo(text.end)
                    top.linkTo(text.top)
                    end.linkTo(parent.end)
                    width = Dimension.wrapContent
                }
                .wrapContentSize()
                .padding(start = 4.dp)
                .noRippleClickable {
                    onInformationButton()
                }
        )

        createHorizontalChain(text, image, chainStyle = ChainStyle.Packed(0F))
    }
Ответ принят как подходящий

Вместо использования макета ограничений мы можем добавить вес со значением заполнения как false.

            Row(modifier = Modifier
                    .fillMaxWidth()
                    .wrapContentHeight()
                    .padding(vertical = 5.dp, horizontal = 10.dp),
                verticalAlignment = Alignment.CenterVertically) {
                Text(
                    text = description,
                    style = AITypography.current.bodyXSmall,
                    color = aiTextHeadingDark,
                    modifier = Modifier.weight(1f, fill = false)
                )
                Icon(
                    modifier = Modifier
                        .defaultMinSize(24.dp)
                        .clickable { onInformationButton() },
                    painter = painterResource(id = R.drawable.ic_information_grey),
                    contentDescription = null
                )
            }

Другие вопросы по теме