Hi everyone, TL:DR : Is there a way to use `BoxWi...
# compose-android
j
Hi everyone, TL:DR : Is there a way to use
BoxWithConstraint { }
inside a
Column
with
Modifier.width(IntrinsicSize.Min)
I'm currently working on a chat feature in my Jetpack Compose app and I'm trying to create a chat bubble that has a minimum size but can expand to almost the entire size of the parent, depending on the content of the message. Within this chat bubble, there can be several composables that will take up the maximum size of the parent without making it bigger. Could anyone please help me understand how I can achieve this behavior with Jetpack Compose? I'm not sure how to use the available modifiers to make the chat bubble adapt to the content while respecting the minimum size. I tried with the modifier
Modifier.width(IntrinsicSize.Min)
and it works unless there is a child using
BoxWithConstraint
. I've got the error:
java.lang.IllegalStateException: Asking for intrinsic measurements of SubcomposeLayout layouts is not supported.
Unfortunately, it's a 3rd party library that uses this component and I can't remove it. Is there a workaround I can use to achieve the same result? Thank you in advance for your help!
Here is a small sample that reproduces the expected behaviour and crash when adding a BoxWithConstraint
Copy code
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppTheme {
                Surface(modifier = Modifier.fillMaxSize(), color = Color.White) {
                    Column(verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) {

                        ChatBubble()
                        ChatBubble()
                        ChatBubble()
                    }
                }
            }
        }
    }
}

@Composable
fun ChatBubble() {
    Surface(
        modifier = Modifier
            .wrapContentSize()
            .defaultMinSize(minWidth = 150.dp, minHeight = 36.dp)
            .padding(5.dp),
        color = Color.LightGray,
        shape = RoundedCornerShape(percent = 10)
    ) {
        Column(
            modifier = Modifier
                .width(IntrinsicSize.Min)
                .widthIn(min = 150.dp),
            verticalArrangement = Arrangement.Center
        ) {
            Text(text = "Opt header text", modifier = Modifier.background(Color.Red).fillMaxWidth())

            Text(text = "Content body", modifier = Modifier.background(Color.Cyan).fillMaxWidth())

            Text(text = randomString())

//            BoxWithConstraints { }
        }
    }
}

val charPool : List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')

fun randomString() = (1..Random.nextInt(0, 60))
    .map { Random.nextInt(0, charPool.size).let { charPool[it] } }
    .joinToString("")
a
Tl;dr: No. This is a circular dependency.
BoxWithConstraints
needs the incoming constraints to decide its content, including its size, and the parent needs the sizes of its children, including the
BoxWithConstraints
, to decide the autual constraints used to measure them.
So what is that
BoxWithConstraints
? If it can be ignored in minimum size calculation, you can write a custom layout that excludes it from intrinsic size queries.
j
Concretely, it is a component that can render markdown, it can be a little bit of text, an image, a table etc. Unfortunately this cannot be ignored for the calculation of the minimum size
a
Then I'm afraid what you want is not possible.
j
I was afraid to hear that but I understand. Thank you for your time
z
the BoxWithConstraints is in a 3P library?
j
Yes it's in a 3P library. Actually, after a double check it's not a
BoxWithConstraints
but a
Layout
.