Any tips on how to get height and width of a compo...
# compose
c
Any tips on how to get height and width of a composable at runtime after it's been drawn to the screen? My backend accepts a height and width param for an image url, but I won't know the exact size to request the image until it's laid out and so I'm looking to write a composable that knows how to do this using glide + accompanist. Just need a hint in terms of how I can get width and height after it's laid out I think. The fact that I'm using glide + accompanist is a detail (i think 😄 ) In classic android view-land we did this by making use of the ktx method called doOnLayout
Copy code
fun ImageView.loadImageToSize(url: String) {
    this.doOnLayout { <--- ktx method that replaced OnGlobalLayoutListener
         // it.width and it.height are accessible here
...
}
a
The
requestBuilder
parameter of
GlideImage
is giving you an
IntSize
which is the size. https://github.com/chrisbanes/accompanist/blob/main/glide/src/main/java/dev/chrisbanes/accompanist/glide/GlideImage.kt#L106
As for your question, you can use
BoxWithConstraints
.
c
@Albert Chang hmm. I wouldn't just use GlideImage?
e.g.
Copy code
GlideImage(
    data = imageUrl,
    contentDescription = null,
    requestBuilder = {
        size: IntSize -> //set imageUrl to have size.height and size.width?
    }
)
c
@eygraber thanks! What solution did you end up going with? I think requestBuilder is exactly what I need, but I can't figure out how to modify the url inside of requestBuilder. Let me know if you went that route.
a
I'm not familiar with Glide but can't you just call
RequestBuilder.load(newUri)
?
c
Yeah. I'm not familiar with this whole concept of a
requestBuilder
but I think I have something that'll work
Copy code
GlideImage(
    data = imageUrl,
    contentDescription = null,
        requestBuilder = { size: IntSize ->
            data(imageUrl + "?width=" + size.width)
    }
)
Running now... 🤞
e
I haven't built it yet, but the idea is that we're going to treat the url as state. So before we have a size the state coming into the Composable will either be an indicator to use a local resource (by wrapping the url in a sealed class) or a url with a very small size that acts as a thumbnail (if the aspect ratio is known in advance). Once we get the size, we'll emit it to our state collector (kind of like a ViewModel), which will emit the state with the url rewritten to have the size information.
c
Seems like that works. Doing a few more tests! Thanks @Albert Chang and @eygraber It would seem that if I use data in requestBuilder, that I wouldn't need to pass it in as the data param into the composable but this should work for me.
It seems to be acting a little funky when I give it an aspect ratio as a modifier... but I'll keep pressing to see if I can figure it out.
a
@eygraber If you use
BoxWithConstraints
, which is what accompanist is using internally, you'll get the size before the request is made, so you don't need a thumbnail anyway.
c
False alarm. It all works as expected. Awesome! For anyone that stumbles upon this in the future, the solution I came to was this
Copy code
GlideImage(
    data = imageUrl,
    contentDescription = null,
        requestBuilder = { size: IntSize ->
            data(imageUrl + "?width=" + size.width +"&height=" + size.height)
    }
)
Really easy! The only thing if Chris Banes is maybe listening in is do you think it's worth filing a bug report to be able to omit the initial
data = ...
if I load
data()
in the
requestBuilder
? Or is it such a minor thing that it's not worth it?