1

I'm trying to build something similar to the following using Jetpack Compose ConstraintLayout.

enter image description here

I want to understand how can I create a vertical chain with respect to the Image. When I try to use the createVerticalChain() function, that overrides my given constraints and chains it w.r.t the parent instead.

Here's my current code if that's any helpful

@Composable
fun GreetingWithConstraintLayout(name: String) {
    ConstraintLayout(modifier = Modifier.fillMaxSize()) {
        val(ivIcon, tvHello, tvBye) = createRefs()
        createVerticalChain(tvBye, tvHello, chainStyle = ChainStyle.Packed)
        Image(
            painter = painterResource(id = R.drawable.ic_launcher_background),
            contentDescription = null,
            modifier = Modifier
                .size(80.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colors.primary, CircleShape)
                .constrainAs(ivIcon) {
                    start.linkTo(parent.start)
                    top.linkTo(parent.top)
                }
        )
        Text(
            text = "Hello $name!",
            modifier = Modifier.constrainAs(tvHello) {
                start.linkTo(ivIcon.end, 8.dp)
                top.linkTo(ivIcon.top)
                bottom.linkTo(tvBye.top)
            }
        )
        Text(
            text = "Bye $name!",
            modifier = Modifier.constrainAs(tvBye) {
                start.linkTo(tvHello.start)
                top.linkTo(tvHello.bottom)
                bottom.linkTo(ivIcon.bottom)
            }
        )
    }
}

I can't find any example similar to this use case online. I'm not even sure if this can be done? Thank you!

che10
  • 2,176
  • 2
  • 4
  • 11

3 Answers3

2

Try constraining the chain

  val chain = createVerticalChain(tvBye, tvHello, chainStyle = ChainStyle.Packed)
  constrain(chain) {
     top.linkTo(ivIcon.top)
     bottom.linkTo(ivIcon.bottom)
  }
hoford
  • 4,918
  • 2
  • 19
  • 19
0

The Only Problem I see is your Image is not constraint properly Also your ConstraintLayout is using fillMaxSize() which i think you can change to fillMaxWidth() if that Okay its fine both ways depending on need . Try the below composable i made few changes i think it works fine .

@Composable
fun GreetingWithConstraintLayout(name: String) {
ConstraintLayout(modifier = Modifier.fillMaxSize()) {
    val (ivIcon, tvHello, tvBye) = createRefs()
    Image(
        painter = painterResource(id = R.drawable.ic_launcher_background),
        contentDescription = null,
        modifier = Modifier
            .size(120.dp)
            .clip(CircleShape)
            .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
            .constrainAs(ivIcon) {
                start.linkTo(parent.start)
                top.linkTo(parent.top)
                bottom.linkTo(parent.bottom)
            }
    )
    Text(
        text = "Hello $name!",
        modifier = Modifier.constrainAs(tvHello) {
            start.linkTo(ivIcon.end, 8.dp)
            top.linkTo(ivIcon.top)
            bottom.linkTo(tvBye.top)
            end.linkTo(parent.end)
            width = Dimension.fillToConstraints
        }
    )
    Text(
        text = "Bye $name!",
        modifier = Modifier.constrainAs(tvBye) {
            start.linkTo(tvHello.start)
            top.linkTo(tvHello.bottom)
            bottom.linkTo(ivIcon.bottom)
            end.linkTo(parent.end)
            width = Dimension.fillToConstraints
        }
    )
    createVerticalChain(tvBye, tvHello, chainStyle = ChainStyle.Packed)
}
}
ADM
  • 20,406
  • 11
  • 52
  • 83
  • Thanks @ADM This does not work unfortunately. It just centers the image too since we added the constraint for it to the bottom of parent which gives an illusion that the chain is working, but the chain is still relative to the parent and not the Image. If I add any sort of bias on the image, the texts still stay aligned to the parent. – che10 Jul 22 '22 at 11:15
  • it removes all margins – user924 Apr 11 '23 at 20:20
0

What you need in order to make it works is: Modifier.wrapContentHeight(align = Alignment.Top).

This is how it looks like in emulator: enter image description here

And the code (I removed some not needed constraints and use Material3 color scheme)

@Composable
fun GreetingWithConstraintLayout(name: String) {
    ConstraintLayout(modifier = Modifier.wrapContentHeight(align = Alignment.Top).fillMaxWidth()) {
        val (ivIcon, tvHello, tvBye) = createRefs()
        Image(
            painter = painterResource(id = R.drawable.ic_launcher_background),
            contentDescription = null,
            modifier = Modifier
                .size(80.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colorScheme.primary, CircleShape)
                .constrainAs(ivIcon) {
                    start.linkTo(parent.start)
                    top.linkTo(parent.top)
                }
        )
        Text(
            text = "Hello $name!",
            modifier = Modifier.padding(start = 16.dp).constrainAs(tvHello) {
                start.linkTo(ivIcon.end)
                top.linkTo(parent.top)
                bottom.linkTo(parent.bottom)
            }
        )
        Text(
            text = "Bye $name!",
            modifier = Modifier.padding(start = 16.dp).constrainAs(tvBye) {
                start.linkTo(ivIcon.end)
                top.linkTo(parent.top)
                bottom.linkTo(parent.bottom)
            }
        )
        createVerticalChain(tvBye, tvHello, chainStyle = ChainStyle.Packed)
    }
}
MiguelHincapieC
  • 5,445
  • 7
  • 41
  • 72