androidandroid-jetpack-composeconstraintsandroid-constraintlayoutandroid-jetpack-compose-material3

Convert XML Constraint Layout to Jetpack Compose - Chain Style, Bias


I am trying to create a specific layout with two views: a TextView and an ImageView. The TextView is dynamic, meaning the length of the text can vary. If the length of the text is less than the width of the device, the ImageView should align to the end of the TextView. However, if the length of the text exceeds the width of the device, the ImageView should be positioned at the end of the device's width. The text can span multiple lines, depending on the content.

I'm just starting with Jetpack Compose and have created a layout using XML's ConstraintLayout. I'm trying to convert this layout to Jetpack Compose, but I'm unsure about the equivalent methods for layout_constraintHorizontal_bias, layout_constraintHorizontal_chainStyle, and layout_constrainedWidth in Jetpack Compose.

Here is the complete XML code that I'm working with:

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

What I tried is:

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

Solution

  • Instead of using constraint layout we can add weight with fill value as 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
                    )
                }