Can't represent a size of 214748364 in Constraints

7.2k Views Asked by At

I just created a simple Composable and wished to render it using a Layout, but while implementing the solution, I stumbled upon this error in the measurement phase.

java.lang.IllegalArgumentException: Can't represent a size of 214748364 in Constraints
        at androidx.compose.ui.unit.Constraints$Companion.bitsNeedForSize(Constraints.kt:408)
        at androidx.compose.ui.unit.Constraints$Companion.createConstraints-Zbe2FdA$ui_unit_release(Constraints.kt:368)
        at androidx.compose.ui.unit.ConstraintsKt.Constraints(Constraints.kt:438)
        at androidx.compose.ui.unit.ConstraintsKt.Constraints$default(Constraints.kt:423)
        at com.gmarsk.aiare.MainActivity$InstructionsScreen$DisplayCard$1.measure-3p2s80s(MainActivity.kt:514)
        at androidx.compose.ui.node.InnerPlaceable.measure-BRTryo0(InnerPlaceable.kt:54)

This was when I tried this

val sampleComposable = measurables[1].measure(
                Constraints(
                    minHeight = constraints.maxHeight * 7 / 10,
                )
            )

Anyone stumble upon this before? What's the solution if it is not a bug, in which case please let me know.

Now, the issue here I think is the fact that I am nesting two Layout Composables,

Layout(
content = {
 Dummy1()
 Dummy2()
 NestedLayoutComposable() // It contains a Layout Composable itself
}{ measurables, constraints ->
 val nlc = measurables[2].measure(
  Constraints(
   minHeight = constraints.maxHeight * 7/10
  )
 )
 layout(constraints.maxWidth, constraints.maxHeight){
  nls.place(0, 0)
 }
}
)

Where The nestedLayoutComposable again has a Layout and that is where the crash occurs, it is at this line

            Layout(
                content = {
                    Text(text = "Random")
                    Box {
                        Image(painter = AppUtils.getRandomImagePainter(), contentDescription = "")
                    }
                }
            ) { measurables, constraints ->
                val text = measurables[0].measure(constraints)
/*This line -->*/   val image = measurables[1].measure(
                    Constraints(
                        maxWidth = constraints.maxWidth * 90 / 100,
                        minHeight = constraints.maxHeight * 7 / 10
                    )
                )

                layout(constraints.maxWidth, constraints.maxHeight) {
                    instruction.place(
                        (constraints.maxWidth - instruction.width) / 2,
                        0
                    )
                    illustration.place(
                        (constraints.maxWidth - illustration.width) / 2,
                        illustration.height / 2
                    )
                }
            }

So I know that the issue is with the Layout Composable being nested within one another but that still doesn't explain WHY the error occurs, and HOW to resolve it, and so those are the prime queries of this post, and that is what I expect the answers to include, thank you.

5

There are 5 best solutions below

1
On

This basically happens when you jam much more than the composable has room for to display.

I have reproduced it using a very long String for a List item

1
On

This happened to me when I tried to use a Slider inside a Column that had Modifier.width(IntrinsicSize.Min), no matter whether the column is its direct parent or not. Though the exception disappears when I use another overload of the slider where you provide a lambda to the thumb parameter but this time the slider doesn't have a thumb. The exception also disappears when I specify a fixed width on the slider.

It's a bug.

Edit: fixed, just needed to update libs.

Edit 2: the libraries were:

  • org.jetbrains.kotlin:kotlin-bom, updated from 1.8.0 to 1.9.0
  • androidx.compose:compose-bom, updated from 2022.10.00 to 2023.06.01 and the respective androidTestImplementation though I don't think the latter was necessary since I didn't write tests

The minimum SDK version was 31

0
On

In your case it's because you can't measure anything with multipliers of Constraints.Infinity. Because in source code of createConstraints function

 internal fun createConstraints(
        minWidth: Int,
        maxWidth: Int,
        minHeight: Int,
        maxHeight: Int
    ): Constraints {

        //  Because of this check and bitsNeedForSize
      
        val heightVal = if (maxHeight == Infinity) minHeight else maxHeight
        val heightBits = bitsNeedForSize(heightVal)

        val widthVal = if (maxWidth == Infinity) minWidth else maxWidth
        val widthBits = bitsNeedForSize(widthVal)
}

converts heightVal to 0 when passed height is Constraints.Infinity when you modify it you send a value to bitsNeedForSize that overflows maxrange and it crashes with

    private fun bitsNeedForSize(size: Int): Int {
        return when {
            size < MaxNonFocusMask -> MaxNonFocusBits
            size < MinNonFocusMask -> MinNonFocusBits
            size < MinFocusMask -> MinFocusBits
            size < MaxFocusMask -> MaxFocusBits
            else -> throw IllegalArgumentException(
                "Can't represent a size of $size in " +
                    "Constraints"
            )
        }
    }

Simple check should be whether the dimension you use is Constraints.Infinity using hasBoundedHeight or constraints.min/maxHieght == Constraints.Infinity

Also another check should be for min constraints not being bigger than maxConstraints so

val wrappedConstraints = constraints.copy(
    minHeight = if (constraints.hasBoundedHeight)
        (constraints.maxHeight * 7 / 10).coerceAtMost(constraints.maxHeight)
    else 0,

)

using such a Constraints to measure your content Composables won't crash.

Also to set your custom layout height if it has a Modifier.fillMaxHeight() or Modifier.height(100) by checking hasFixedHeight and not a infinite with hasBoundedHeight

  val contentHeight = // This some height you get with max, sum or your logic

  val totalHeight = if(hasBoundedHeight && hasFixedHeight){
        constraints.maxHeight
    }else {
        contentHeight.coerceIn(constraints.minHeight.toFloat(), constraints.maxHeight.toFloat())
    }

When it doesn't have a size Modifier or a Modifier with Modifier.height(min=0.dp, max=500.dp)

you say let this Composable as big as content but within range of Constraints from size Modifier.

This check also makes sure your Composable do not crash when intrinsic height modifier is assigned.

java.lang.IllegalArgumentException: Can't represent a size of 2147483647 in Constraints
1
On

In my case similar crash was caused by scrollable Column inside another scrollable Column. Check if you do not have such a case in your compose hierarchy.

0
On

For anyone else that comes across this, the problems is that scrollable views set maxHeight to Constraints.Infinity, which is represented as Int.MAX_VALUE. So if your layout assumes a bounded height, it's going to overflow the int value.