fillMaxHeight() inside Row

Viewed 908

My question is related to this one: How to achieve this layout in Jetpack Compose

I have this code:

@Composable
fun TestUi() {
    Row {
        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier
                .background(color = Color.Yellow)
                .fillMaxHeight()
        ) {
            CircularProgressIndicator()
        }
    
        Image(imageVector = vectorResource(id = R.drawable.ic_launcher_background))
    }
}

I expected to get this:

Expected result

But I got this instead:

Actual result

How can I get the Box to fill all the available height without affecting the height of the Row?

I know I could use a ConstraintLayout to solve this, but it seems too much for such a simple use case.

5 Answers

Have a look at the Layout Composable or Modifier. You can measure the defining element first and then provide modified constraints to the dependent element. If you want to use this as a modifier you should add a size check for the list.

Layout(content = {
    Box(modifier = Modifier
        .size(width = 30.dp, height = 50.dp)
        .background(Color.Green))
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .background(color = Color.Yellow)
            .fillMaxHeight()
    ) {
        CircularProgressIndicator()
    }
}) { measurables: List<Measurable>, constraints: Constraints ->
    val heightDef = measurables[0].measure(constraints)
    val other = measurables[1].measure(
        constraints.copy(
            maxHeight = heightDef.height,
            maxWidth = constraints.maxWidth - heightDef.width)
    )
    layout(
        width = heightDef.width + other.width,
        height = heightDef.height
    ) {
        other.placeRelative(0,0)
        heightDef.placeRelative(other.width,0)
    }
}

For height, instead of fillMaxHeight, just put

.height(vectorResource(id = R.drawable.ic_launcher_background).defaultHeight)

Just for reference, here's the equivalent design implemented with ConstraintLayout:

@Composable
fun TestUi() {
    ConstraintLayout {
        val (box, image) = createRefs()

        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier
                .background(color = Color.Yellow)
                .constrainAs(box) {
                    height = Dimension.fillToConstraints
                    top.linkTo(parent.top)
                    bottom.linkTo(parent.bottom)
                    start.linkTo(parent.start)
                }
        ) {
            CircularProgressIndicator()
        }

        Image(
            imageVector = vectorResource(id = R.drawable.ic_launcher_background),
            modifier = Modifier.constrainAs(image) {
                top.linkTo(parent.top)
                start.linkTo(box.end)
            }
        )
    }
}

you can use constraintlayout, the trick is in this part of the code height =Dimension.fillToConstraints

  ConstraintLayout(){
        val (boxRef, imgRef) = createRefs()

        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier
                .background(color = Color.Yellow)
                .constrainAs(boxRef){
                    start.linkTo(parent.start)
                    end.linkTo(imgRef.start)
                    top.linkTo(parent.top)
                    height = Dimension.fillToConstraints
                }

        ) {
            CircularProgressIndicator()
        }

        Image(imageVector = vectorResource(id = R.drawable.ic_launcher_background),modifier=Modifier.constrainAs(imgRef){
            start.linkTo(boxRef.end)
            top.linkTo(parent.top)
            end.linkTo(parent.end)
        })
    }

Related