What is the proper way to get the height of the sc...
# compose
s
What is the proper way to get the height of the screen in Compose for something like this Linear Gradient? I have to specify the height, but what I really want is from the top of the view to the end of the view, which can change depending on the running device. What’s the right way to do this in compose?
Copy code
Column(
            Modifier
                .weight(1f)
                .fillMaxSize()
                .background(
                    VerticalGradient(
                        colors = listOf(
                            Color(125, 206, 250),
                            Color(82, 88, 245),
                        ),
                        startY = 0f,
                        endY = 100f
                    )
                )
        ) {
            SecondarySection()
        }
l
I would like us to tweak the API here so this is easier, but right now the way to do this is to use the
drawWithCache
modifier (which will give you the full view size after layout is done) and create the vertical gradient there, and then use it in the
draw
👍🏼 1
something like
Copy code
.drawWithCache {
  gradient = VerticalGradient(..., endY = size.height)
  onDraw {
    drawRect(gradient, ...)
  }
}
s
@Leland Richardson [G] Can we file a bug to track this? The API is verbose, unintuitive, and undiscoverable.
I’m happy to file it, but I’m not sure where it’d go.
I hope it’s not the android issue tracker. That’s where unstarred bugs go to die.
That worked. Thanks Leland.
l
feel free to +1 or something
v
Thanks for the tip, Leland. I am running into a similar situation where I want to overlay a Gradient on top of a
CoilImage
Composable without having to set a predefined width as is required by
Modifier.border
. This seems like a common use case. I tried the
drawWithCache
approach, but I am bumping into a situation where the Image is placed on top of the Gradient. I tried a variety of `BlendMode`'s and `alpha`; and
onDrawWithContent
to draw the Image first, but I can't seem to get the right combination. An alternative route is to place the both the
Image
and
VerticalGradient
in a
Box
, but that seems undesirable. Any tips from someone out there would be appreciated!
Copy code
CoilImage(
    request = ImageRequest.Builder(ContextAmbient.current)
        .data(imageUrl)
        .transformations(CircleCropTransformation())
        .build(),
    loading = {
        Box(Modifier.fillMaxSize()) {
            CircularProgressIndicator(Modifier.align(Alignment.Center))
        }
    },
    // Add the gradient as a modifier to the Image here
    modifier = Modifier.preferredSize(128.dp)
        //.border(width = 128.dp, brush = gradient, shape = CircleShape)
        .drawWithCache {
            
            val black30Percent = Color(0, 0, 0, 30)
            val green70Percent = Color(0, 255, 0, 70)
            val red100Percent = Color(255, 0, 0, 100)
            
            val gradient = VerticalGradient(
                colors = listOf(black30Percent, green70Percent, red100Percent),
                startY = 0.0f,
                endY = 100.0f
            )

            onDraw {
                drawCircle(brush = gradient, blendMode = ?) // Maybe something here?
            }
        }
)
I was able to answer my own question after a Slack search. It looks like I was on the right track with
onDrawWithContent
. In this comment, Nick Butcher linked out to a
Modifer.scrim
extension function he created in the Owl Jetpack Compose sample for an image overlay gradient. https://kotlinlang.slack.com/archives/CJLTWPH7S/p1600690994127100 https://github.com/android/compose-samples/blob/master/Owl/app/src/main/java/com/example/owl/ui/utils/Scrim.kt This works for my use case above. I know there are a lot of nuances for a new API, but I would also +1 an official Modifier function for something like
Modifer.gradient(colors = , shape = ,)
so that it's easily discoverable.