Why can't the height property of Modifier be written in Jetpack Compose?

Viewed 68

I define a val modifier with height(30.dp), then I pass it with modifier.height(5.dp) to Spacer function.

I think the final height of Spacer should be 5.dp because I have overwritten the height of val modifier.

It seems that the height of Spacer isn't 5.dp, what's wrong with my code?

Code A

val modifier = Modifier.fillMaxWidth().height(30.dp)
    
Spacer(modifier = modifier.height(5.dp))
2 Answers

Order of Modifiers in Composable functions is important.

Refer to this solution and other solutions in the question for more info on this.


If you want the height inside the Spacer to be the final one, you have to use Modifier.then().

The given code

val modifier = Modifier.fillMaxWidth().height(30.dp)
Spacer(modifier = modifier.height(5.dp))

is same as

Spacer(modifier = Modifier.fillMaxWidth().height(30.dp).height(5.dp))

But, if you change it using then() like this

val modifier = Modifier.fillMaxWidth().height(30.dp)
Spacer(modifier = Modifier.height(5.dp).then(modifier))

It would become

Spacer(modifier = Modifier.height(5.dp).fillMaxWidth().height(30.dp))

Sample code

@Composable
fun OrderOfModifiers() {
    val modifier = Modifier
        .fillMaxWidth()
        .height(30.dp)
    Column(
        modifier = Modifier
            .fillMaxSize(),
    ) {
        Spacer(modifier = modifier
            .height(5.dp)
            .background(DarkGray),
        )
        Spacer(modifier = Modifier
            .height(5.dp)
            .then(modifier)
            .background(Cyan),
        )
    }
}

Sample screenshot

screenshot

When chaining size modifiers such as Modifier.height(height1).height(height2) first one is used by design. As in Abhimanyu's answer using Modifier.then() doesn't change this either, first one is used. Then changes in which order modifiers are applied.

This approach creates opportunity for developers to assign default size when no modifier with size is set by devs use this Composable. Slider is built in similar fashion, it covers full width by default.

When you create a Composable such as

@Composable
private fun MyComposable(modifier: Modifier=Modifier){
    Box(modifier = modifier
        .fillMaxWidth()
        .size(48.dp))
}

And use it as

MyComposable(modifier = Modifier.border(3.dp, Color.Green))

Will result having a Composable with full screen width and 48.dp height. If you set a Modifier with a size default one gets overridden

MyComposable(modifier = Modifier.border(3.dp, Color.Red).size(50.dp))

enter image description here

Related