https://kotlinlang.org logo
#compose
Title
# compose
l

Lucas Kivi

01/10/2023, 12:38 AM
I have a button with conditional content:
CircularProgressIndicator
and
Text
. I want the button to stay the same size across content changes. This is easy enough if we just convert the text size in
Sp
to
Dp
and set the
CircularProgressIndicator
’s size padding accordingly. However, when we consider that the text may become multiple lines when font size is increased for accessibility this solution no longer works. I am considering building a
SubcomposeLayout
implementation that measures the
Text
and sets the button height accordingly and then can conditionally forego placing the
Text
. This seems a little computationally expensive. I don’t think
Intrinsics
will solve my problem. Does anyone have a suggestion for me before I build out my abstract
SubcomposeLayout
solution?
1
f

Francesc

01/10/2023, 12:48 AM
I would go with intrinsics. Provided one dimension is set (like the width), you can calculate how tall each child composable wants to be and choose the largest of the set, then build a set of
Constraints.fixed(width = constraints.maxWidth, height = max(all children height))
then lay one child or the other based on your logic
Subcompose is more specific and comes with a performance penalty, if you can get away with intrinsics that's the better solution
l

Lucas Kivi

01/10/2023, 12:51 AM
Right…
I haven’t done much with intrinsics
so you are still saying build a custom
Layout
, right?
f

Francesc

01/10/2023, 12:52 AM
if you don't know how much space you are going to need ahead of time, then yes, otherwise use a
Box
to wrap both children
l

Lucas Kivi

01/10/2023, 12:56 AM
Ok so in the case of the
Box
how do you extract it’s
Intrinsic
height prior to
Composition
? For example we want to see the height of height of the
Text
here
Copy code
Box {
    Text("Intrinsics are fun")
}
f

Francesc

01/10/2023, 12:57 AM
you would use a
Box
(or
CrossFade
) if your height is fixed. If not, use a layout, then use the measure the required height use
maxIntrinsicHeight
for each composable, then use the max of those heights to set the actual height of the
Layout
. See this https://developer.android.com/jetpack/compose/layouts/intrinsic-measurements#intrinsics-in-layouts
l

Lucas Kivi

01/10/2023, 12:58 AM
The issue came up because the height must change with accessibility 🤔 so it is fixed in
Sp
f

Francesc

01/10/2023, 1:00 AM
I have to run, but you could check this out where I use intrinsyc widths to ensure the children are all of the same width, similar to what you are after (but you seem to be after height, though the principle is the same) https://github.com/fvilarino/Weather-Sample/blob/c7e0916d4311c5ff5f3fc5cf620484957[…]ncescsoftware/weathersample/shared/composable/EqualSizeTiles.kt
l

Lucas Kivi

01/10/2023, 1:01 AM
Cheers man
you are a hero
a

Ahaisting

01/10/2023, 1:03 AM
I could for sure see myself using
alpha
on the
Text
as a simple hack… probably doesn’t satiate you, but nobody has to know 😸
l

Lucas Kivi

01/10/2023, 1:04 AM
You are the devil in my ear 😉
@Francesc I would be interested to hear how you would forego placing one of your tiles in that example. That is really the hardest part. Because I would need to enter both the
Text
and the
CircularProgressIndicator
into the
Layout
, measure them, and then withhold placement of one or the other. It seems difficult to do this robustly using
Intrinsics
.
tLeaning further and further towards
Heavily considering making a deal with the devil 😈
a

Alex Vanyo

01/10/2023, 1:23 AM
then can conditionally forego placing
That’s probably the cleanest solution, and no need to use
SubcomposeLayout
or anything!
You can conditionally not call
place
by passing a
Modifier
to the component you want to take up space, but don’t show:
Copy code
Modifier.layout {
    val placeable = measurable.measure(constraints)
    layout(placeable.measuredWidth, placeable.measuredHeight) {
        if (showProgressIndicator) {
            placeable.place(0, 0)
        }
    }
}
l

Lucas Kivi

01/10/2023, 1:35 AM
It seems I haven’t been taking full advantage of `Modifier`s. 😻 That is indeed as clean as it comes.
I just knew I would brush genius here 👼
a

Alex Vanyo

01/10/2023, 1:36 AM
Although it looks like there’s a bug with that right now… https://kotlinlang.slack.com/archives/CJLTWPH7S/p1672839190220699 So you might need to do something like
Copy code
if (showProgressIndicator) {
    Modifier
} else {
    Modifier.layout {
        val placeable = measurable.measure(constraints)
        layout(placeable.measuredWidth, placeable.measuredHeight) {}
    }
}
l

Lucas Kivi

01/10/2023, 1:39 AM
You have saved me a lot of time and effort, for that I thank you 🫶
a

Alex Vanyo

01/10/2023, 1:42 AM
Issue you can track for having something like this built-in: https://issuetracker.google.com/issues/158837937
l

Lucas Kivi

01/10/2023, 1:43 AM
🐐 ☝️
Worked exactly how I expected! Thanks again @Alex Vanyo
83 Views