I was curious why `drawIntoCanvas { it.nativeCanva...
# compose-android
t
I was curious why
drawIntoCanvas { it.nativeCanvas.drawRenderNode(...) }
wasn't drawing anything. Turns out you need to call
RenderNode.setPosition()
before drawing! So a nice cached render modifier for API >= 29 is:
Copy code
fun Modifier.drawCached(): Modifier = drawWithCache {
    val width = size.width.roundToInt()
    val height = size.height.roundToInt()

    val renderNode = RenderNode("drawCached")
    renderNode.setPosition(0, 0, width, height)

    onDrawWithContent {
        val recordingCanvas = renderNode.beginRecording(width, height)
        draw(this, layoutDirection, Canvas(recordingCanvas), size) {
            this@onDrawWithContent.drawContent()
        }
        renderNode.endRecording()
        drawIntoCanvas { it.nativeCanvas.drawRenderNode(renderNode) }
    }
}
This works well for expensive composables in lazy layouts like HorizontalPager, e.g. when layering several layouts in the child pages.
r
You could just use a
graphicsLayer{}
?
t
Curiously this outperforms that, but I'll test again
r
@Nader Jawad
n
They should be identical in performance. Various container composables implicitly place child composables onto their own graphicsLayer as well through the placeWithLayer API
t
I may be placing
graphicsLayer
in the wrong place. The context is a parallax animation inside HorizontalPager, so I wanted to render a Composable to a RenderNode to avoid re-drawing when translating it; however, I am using a custom
Alignment
implementation for the parallax offset instead of using
graphicsLayer { translationX = ... }
. I will rework this and report back.
r
graphicsLayer { translationX = ... }
is pretty much free
under the hood it’s just repositioning the
RenderNode
n
Custom Alignment can cause additional invalidations and depending on the use case using graphicsLayer translation may help here
r
It’s basically what `ListView`/`RecyclerView` do to handle scrolling
t
cool, using
Modifier.layout
with
placeRelativeWithLayer
works pretty well.
I think my performance issues are just rendering the initial layout now.