Create vertical chain with respect to other element in jetpack compose ConstraintLayout?

2.4k Views Asked by At

I want to chain title and description text centered with respect to image with chainStyle.Packed how to achieve this in jetpack compose.

when i use createVerticalChain() its create chain with respect to parent container that's not what i want, is there a way to achieve this?

enter image description here

3

There are 3 best solutions below

1
On

There are two solutions. The first solution requires that the height of the content on the right of the circle is fixed, while in the second solution, it is not fixed but is bound by constraints:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        startActivity(intent)

        setContent {
            Column(modifier = Modifier.fillMaxSize()) {
 
                // First solution

                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .wrapContentHeight()
                ) {
                    Box(
                        modifier = Modifier
                            .size(100.dp)
                            .background(color = Color.Red, shape = RoundedCornerShape(50.dp))
                    )

                    Column(
                        modifier = Modifier
                            .height(100.dp)
                            .padding(start = 20.dp), verticalArrangement = Arrangement.Center
                    ) {
                        Text("Line 1 goes here")
                        Text("Line 2 goes here")
                    }
                }

                Spacer(modifier = Modifier
                    .requiredHeight(30.dp)
                    .fillMaxWidth())


                // Second solution

                ConstraintLayout(modifier = Modifier.fillMaxWidth()) {
                    val (left, right) = createRefs()

                    Box(modifier = Modifier
                        .size(100.dp)
                        .background(color = Color.Red, shape = RoundedCornerShape(50.dp))
                        .constrainAs(left) {
                            start.linkTo(parent.start)
                            top.linkTo(parent.top)
                            bottom.linkTo(parent.bottom)
                        })

                    Column(
                        verticalArrangement = Arrangement.Center,
                        modifier = Modifier
                            .padding(start = 20.dp)
                            .constrainAs(right) {
                                start.linkTo(left.end)
                                top.linkTo(left.top)
                                end.linkTo(parent.end)
                                bottom.linkTo(left.bottom)
                                width = Dimension.fillToConstraints
                                height = Dimension.fillToConstraints
                            }) {

                        Text("Line 1 goes here")
                        Text("Line 2 goes here")
                    }
                }
            }
        }
    }
}
0
On

1) Circle and Text rows over an Image

Circle and Text over an Image

  1. Create a VerticalGuideline 50% from an edge
  2. Create an Image view
  3. Make a box with rounded corners to make a circle
  4. Constrain the circle to the VerticalGuideline
  5. Create a Column with your two text items
  6. Constrain them to the end of the circle
@Preview
@Composable
fun CircleWithTextColumnOverImage() {
    ConstraintLayout(
        modifier = Modifier
            .background(Color.White)
            .fillMaxSize()
    ) {

        // View References
        val (image, circle, textColumn) = createRefs()

        // Guide line to constrain circle against
        val verticalGuideline = createGuidelineFromAbsoluteLeft(.5f)

        // Image
        Image(
            painterResource(id = R.drawable.launcher_background),
            contentDescription = "Image Background",
            modifier = Modifier
                .size(100.dp)
                .constrainAs(image) {
                    start.linkTo(parent.start)
                    end.linkTo(parent.end)
                    top.linkTo(parent.top)
                    bottom.linkTo(parent.bottom)
                }
        )

        // Circle
        Box(modifier = Modifier
            .size(100.dp)
            .padding(16.dp)
            .background(color = Color.Red, shape = RoundedCornerShape(50.dp))
            .constrainAs(circle) {
                end.linkTo(verticalGuideline) // <-- Constrained to the VerticalGuideline
                top.linkTo(image.top)
                bottom.linkTo(image.bottom)
            }
        )

        // Text Column
        Column(modifier = Modifier
            .constrainAs(textColumn) {
                start.linkTo(circle.end) // <-- Constrained to the Circle
                top.linkTo(circle.top)
                bottom.linkTo(circle.bottom)
            }) {
            Text("Line 1 goes here")
            Text("Line 2 goes here")
        }
    }
}

2) Circle and Text rows

enter image description here

  1. Make a box with rounded corners to make a circle
  2. Create a Column with your two text items
  3. Constrain them together with a ConstraintLayout
   @Preview  
   @Composable  
   fun CircleWithTextColumn() {  

    ConstraintLayout(modifier = Modifier.fillMaxSize()) {
        val (circle, textColumn) = createRefs()

        // Circle
        Box(modifier = Modifier
            .size(100.dp)
            .padding(16.dp)
            .background(color = Color.Red, shape = RoundedCornerShape(50.dp))
            .constrainAs(circle) {
                start.linkTo(parent.start)
                top.linkTo(parent.top)
            }
        )

        // Text Column
        Column(modifier = Modifier
            .constrainAs(textColumn) {
                start.linkTo(circle.end)
                top.linkTo(circle.top)
                bottom.linkTo(circle.bottom)
            }) {
            Text("Line 1 goes here")
            Text("Line 2 goes here")
        }
    }
}
1
On

Like suggested inside the documentation of createVerticalChain(), you can "Use constrain with the resulting VerticalChainReference to modify the top and bottom constraints of this chain.":

ConstraintLayout(modifier = Modifier.fillMaxSize()) {
    val (box, text1, text2) = createRefs()

    val chainRef = createVerticalChain(text1, text2, chainStyle = ChainStyle.Packed)

    constrain(chainRef) {
        top.linkTo(box.top)
        bottom.linkTo(box.bottom)
    }

    Box(modifier = Modifier
        .size(100.dp)
        .padding(16.dp)
        .background(color = Color.Red, shape = RoundedCornerShape(50.dp))
        .constrainAs(box) {
            start.linkTo(parent.start)
            top.linkTo(parent.top)
        }
    )

    Text("Line 1 goes here",
        modifier = Modifier
            .constrainAs(text1) {
                start.linkTo(box.end)
                end.linkTo(parent.end)
                top.linkTo(box.top)
                bottom.linkTo(text2.top)
                width = Dimension.fillToConstraints
            }
    )

    Text("Line 2 goes here",
        modifier = Modifier
            .constrainAs(text2) {
                start.linkTo(box.end)
                end.linkTo(parent.end)
                top.linkTo(text1.bottom)
                bottom.linkTo(box.bottom)
                width = Dimension.fillToConstraints
            }
    )
}

enter image description here