Hi everyone! I'm trying to use `GraphicsLayer#toIm...
# compose-android
v
Hi everyone! I'm trying to use
GraphicsLayer#toImageBitmap()
api as described here. Everything works except shadows are not being captured no matter what composable in the hierarchy I'm trying to capture. Is there any way to capture shadows as well?
y
Is that because it's not hardware accelerated?
v
Not sure what exactly is not hardware accelerated. Afaik
toImageBitmap
uses hardware acceleration and shadows also drawn using
graphicsLayer
and, I assume, are hardware accelerated
👍🏻 1
s
Hmm, interesting, I was actually able to reproduce this behavior with elevation. I’m not sure why, maybe it’s due to the nature of elevated shadows, since they’re not like regular paint shadows or something similar.
Fortunately, the latest Compose beta introduces new APIs for drawing custom shadows, like outer and inner shadows. These APIs work well and are highly customizable.
... highly customizable
👀 1
v
@Sergey Y. Thank you, that could help. Can you please show a link to the new shadow api? :)
s
Its pretty simple: Modifier.dropShadow, Modifier.innerShadow
l
Hey guys, I just came across this interesting thread. In the case my screen content is a column and the list item is longer than the screen height. Could you help to share if there is a way to capture the full content including the off screen items?
v
Thanks, @Sergey Y.! I'll take a look ❤️ @Long Tran You should probably start a new thread for that.
s
Yeah, it’s better to start a new thread, because unfortunately, I don’t know how to take long screenshots in Compose. GraphicsLayer only captures what’s currently rendered on the screen. If it’s not a lazy layout, then theoretically the Row or Column can be rendered all at once. But if it’s a lazy layout, it only creates items lazily as needed, so GraphicsLayer won’t capture items outside the visible bounds.
l
Thanks guys, I’ll start a new thread for this after doing more research
y
@Zach Klippenstein (he/him) [MOD] I seem to associate long screenshots with you. Or am I confusing things
z
yep, i did the original implementation
most of the impl is here, but it won't be directly applicable here since it uses internal APIs to control scrolling via semantics. I don't believe there's a way to call child semantics actions from a composable yet, although I think that was planned. If that existed, you could probably use it to scroll programmatically for a
GraphicsLayer
capture too. If you have access to the
ScrollState
then you don't need that of course.
v
Thanks again @Sergey Y. . I sorted it out. After playing with it it seems somewhat logical that graphics layer doesn't include the elevation shadow since the shadow is dynamic and depends on the position of the view on the screen. So I had to find some "middle-ground" for a static shadow that will "fit most".
Copy code
private fun Modifier.staticShadow(
    elevation: Dp, 
    shape: Shape, 
    yOffset: Dp = elevation/3, 
    basePadding: Dp = elevation/2
): Modifier = this
    .padding(
        start = basePadding,
        end = basePadding,
        top = basePadding - yOffset,
        bottom = basePadding + yOffset,
    )
    .dropShadow(shape) {
        radius = elevation.toPx()
        offset = Offset(0f, yOffset.toPx())
        alpha = .25f
    }
👍 1