How can i have a child element in Box Composable, ...
# compose
y
How can i have a child element in Box Composable, which has only the 1/4 size of the Box Composable? Is it possible to get the width and height of a composable?
Is there something like
Modifier.width(IntrinsicSize.Max / 2)
, unfortunately I can not perform arithmetic operation on
IntrinsicSize.Max
j
what about this ?
Copy code
@Preview
@Composable
fun TestPreview() {
    Box(modifier = Modifier
        .fillMaxSize()
        .background(Color.Black)) {
        Box(
            modifier = Modifier
                .background(Color.Red)
                .fillMaxWidth(0.25f)
                .fillMaxHeight(0.25f)
        )
    }
}
ends up with something like
y
Thanks for your help, it is perfect. Didn’t know you can put fraction into fillMaxWidth()
p
Is there something similar for offset or we have to do it from the layout {} lambda?
j
@Pablichjenkov maybe BoxWithConstraints where you can get min/max of the parent would be easier for this "advanced" stuff I guess use rather ConstraintLayout, it is more powerful and probably do the job better, not sure though your usecase or if there is a desktop version... thinking more about it, I'm not sure how ^^^ is going to work if a parent has scrollable modifier which makes size "infinite" in terms of compose API
y
@Pablichjenkov I also tried to do some offset using padding while arrange the child element inside the box. I guess also ConstraintLayout would be better way to go, if offset get complicated.
p
I see, yeah there is no standard solution for this type of design based on percentage. I do a trick that involves 2 layout passes. Here:
Copy code
BoxWithConstraints(
    modifier = modifier
        .fillMaxSize()
        .onGloballyPositioned { coordinates ->
            boxWithConstraintsHeight = (coordinates.size.height.toFloat())
        }
) { // boxWithConstraintsHeightMax could have been obtained from boxConstraintScope but the
    // value is pre-layout so we are not sure whether the Parent will fill the whole size or nor.
    val boxConstraintScope = this
    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .background(Color.Black),
        //verticalArrangement = Arrangement.spacedBy(20.dp)
    ) {
        val spacerHeight = boxWithConstraintsHeight.times(0.25)
        val spacerHeightDp = with(density) { spacerHeight.toInt().toDp() }
        Log.d("Pablo", "spacerHeightDp = ${spacerHeightDp}")

        val redBoxHeight = boxWithConstraintsHeight.times(2)
        val redBoxHeightDp = with(density) { redBoxHeight.toInt().toDp() }
        Log.d("Pablo", "redBoxHeightDp = ${redBoxHeightDp}")

        Spacer(
            modifier = Modifier
                .fillMaxWidth(0.75F)
                .height(spacerHeightDp)
                .background(Color.Green)
        )
        Box(
            modifier = Modifier
                .background(Color.Red)
                .fillMaxWidth(0.5F)
                .height(redBoxHeightDp)
                .absoluteOffset(y = 100.dp)
                .onGloballyPositioned { coordinates ->
                    boxHeight = (coordinates.size.height.toFloat())
                }
        )
    }
    /* This work with "Row and Column" but the fraction is related to the size that is left to
    fill not the parent size
    Spacer(
        modifier = Modifier.fillMaxWidth().fillMaxHeight(0.5F)
    )
    Box(
        modifier = Modifier
            .background(Color.Red)
            .fillMaxWidth(0.5F)
            .fillMaxHeight(0.5F)
    )*/
}
What I do is wrap a Column/Row within a Box set to fillMaxSize. Then capture the Box layout parameters in onGloballyPositioned, which is invoked after the layout phase finishes. I have a reactive state within the composable hierarchy that reacts to the Box change. Then the children of the Box react to this change.
Modifier.offset() did not work for me. It seems to me that it is ignored, I tried so many ways with that modifier and none has any effect . So what I end up doing is using a Spacer instead.
If you play with above composable you will see you can set your children size based on percentage of the parent which will give you a consistent look in all screen sizes.
But that technique is really not scalable in a composable with a lot of children, I believe Constraint layout is the way to go for now
209 Views