Hi, is there a way i can pass the size of the pare...
# compose
o
Hi, is there a way i can pass the size of the parent, let's say a
Box
to it's child
GlideImage
? if so, whats the best way to do that?
c
BoxWithConstraints
can give you the box’s dimensions. Though it should be noted that it uses
SubcomposeLayout
so has a bit of a performance penalty.
2
f
you can also use
onPlaced
but this comes with a 1 frame delay, but doesn't have the penalty of
BoxWithConstraints
. Alternatively, you can use
Layout
which has neither the penalty nor the delay, but it's a bit more involved
z
What are you trying to do?
Without more context, this is what the layout system’s entire job is: pass information about the parent size to children.
o
i am trying to optimize the size of the image that GlideImage loads by sending it a fixed size (width/height) rather than the using the url that an endpoint sends. for this purpose i need a width and height of the compose to add to url as a query param to load it with glideimage
I was using a local intSize and getting the size from parent
Box
through using
onSizeChanged
and then uses that to pass down to GlideImage, but wondering if there is a better way
f
I haven't run this, but you could try something along these lines
Copy code
@Composable
fun RemoteImage(
    url: String,
    modifier: Modifier = Modifier,
) {
    var updatedUrl by remember { mutableStateOf(Uri.EMPTY) }
    Layout(
        modifier = modifier,
        content = {
            AsyncImage(
                model = updatedUrl,
                contentDescription = null,
            )
        }
    ) { measurables, constraints ->
        val placeable = measurables[0].measure(constraints)
        layout(
            width = constraints.maxWidth,
            height = constraints.maxHeight,
        ) {
            updatedUrl = Uri.parse(url).buildUpon()
                .appendQueryParameter("w", constraints.maxWidth.toString())
                .appendQueryParameter("h", constraints.maxHeight.toString())
                .build()
            placeable.place(0, 0)
        }
    }
}
o
ahh nice 😄 working by hand seems better. but would it have the same performance as @Konstantin Tskhovrebov’s answer?
f
the GitLab snippet uses
onSizeChanged
``onGloballyPositioned`` which incurs a 1 frame delay penalty (these methods they all have a 1 frame delay)
o
yep, that's what i thought, measuring and laying out by hand seems the best option
does using
onSizeChanged
have the same performance issue of 1 frame delay?
z
Any time you’re passing data from one phase (e.g. measurement) to a previous phase (e.g. composition), it’s going to introduce a frame delay
onSizeChanged
,
onPlaced
,
onGloballyPositioned
, etc don’t inherently have a frame delay, the delay comes from data flowing “backwards”
👍 1
o
so it is better to measure and layout ourself like in case of @Francesc’s answer?
z
it doesn’t matter if you write the layout yourself – in this case you’re still passing data backwards from measurement to composition.
To avoid the frame delay,
AsyncImage
would need some way for you to pass it an object that can retrieve the URL lazily, e.g. a
() -> URL
.
👍 1
Assuming
AsyncImage
does not internally need to actually know the URL at composition time
o
is there a better way than?
z
i don’t know the Glide API – but looking at their Compose javadocs it doesn’t look like it
With Coil, it looks like you could maybe use
AsyncImagePainter
and set the request property from measurement? But i’m not sure if that would actually work
o
that would be a huge migration as well as regression for us for one use case
z
i’m surprised none of these libraries can handle this use case
😢 1
so then yea i guess subcomposition is unfortunately the only workaround that won’t introduce a frame delay sad panda
o
could you provide an example for a way to do that?
z
The BoxWithConstraints suggestion above
👍 1
o
gotcha, thank you gratitude thank you
k
In my sample I don't change a layout, just load an image with a correct size
s
For your snippit Konstantin, wouldn’t it then be better to use
androidx.compose.ui.layout.onSizeChanged
instead of
onGloballyPositioned
since you only care for the size. Also not sure about the
fillMaxSize
on that Image itself, would that sometimes make the image take more space than it needs to?