7

In Jetpack Compose, I have a card composable that I want to be a minimum of 100.dp tall. However, if I use heightIn, the card consumes all available height up until the max. How do I set a minHeight without consuming all height?

Surface(
    modifier = heightIn(100.dp, 9999.dp),
) {
    // Content
}

To be clear, what I want is the following algorithm:

height = if (contentHeight > minHeight) {
    contentHeight 
} else {
    minHeight
}
frodo2975
  • 10,340
  • 3
  • 34
  • 41

2 Answers2

16

Use Modifier.defaultMinSize

Surface(
    modifier = Modifier.defaultMinSize(height = 100.dp),
) {
    // Content
}
danartillaga
  • 1,349
  • 1
  • 8
  • 19
3

Edit

To be clear, what I want is the following algorithm:

height = if (contentHeight > minHeight) { contentHeight } else { minHeight }

Modifier.height(contentHeight.coerceAtLeast(minHeight)) is the shortened algorithm.

When a Layout measures and places children it checks constraints. You can find detail answered here about how it works.

For instance column has minHegith = 100.dp, while maxHeight is your composable height in dp. If it's root it's height of screen in dp

Column(modifier=Modifier.heightIn(min=100.dp)) {
   Box(modifier=Modifier.fillMaxSize().background(Color.Yellow))
}

For instance this Box covers whole space because it's min and max constraint is Column's maxHeight. In this case using Modifier.heightIn() won't limit, so you need Modifier.height() such as in my original answer with a fixed value or use custom layout to check and assign .

layout(width, height){} inside Layout.

But there is something to note with Surface that it forces minimum constraints to direct descendant, you can check my answer about Surface here.

Surface(modifier = Modifier.heightIn(min = 100.dp)) {
    Box(
        modifier = Modifier
            .size(300.dp)
            .background(Color.Yellow)
    )
}

This Box in example will cover all of the height because of being Surface's direct descendant.

Surface(modifier = Modifier.heightIn(min = 100.dp)) {
   Column() {
       Box(
           modifier = Modifier
               .size(300.dp)
               .background(Color.Yellow)
       )
   }
}

This one will have 300.dp size while Column covers all available space of Surface

Thracian
  • 43,021
  • 16
  • 133
  • 222
  • 1
    The example I gave was just what I need the algorithm to be, there isn't an actual variable named `contentHeight`. I could get that info by using a custom layout, but I would expect this common use case to be possible without going to that much trouble. – frodo2975 Aug 10 '22 at 15:06
  • coerceAtLeast is extension function that is available for dp, float, int or double `public fun Float.coerceAtLeast(minimumValue: Float): Float { return if (this < minimumValue) minimumValue else this }` – Thracian Aug 10 '22 at 15:09
  • 1
    I don't think you understand, there isn't any variable called `contentHeight`, at least not without doing a custom layout. – frodo2975 Aug 10 '22 at 15:11
  • Unfortunately, this is not an answer to the question. – azizbekian Aug 13 '22 at 09:03