I have question about optimization of Modifier.dra...
# compose
m
I have question about optimization of Modifier.drawWithCache while using for example some animation to move a square path with brush background. Can this example be somehow improved? Thanks a lot.
Copy code
Box(
        modifier = Modifier
            .drawWithCache {
                // this section is cached and not called during animation
                val colorList = listOf(Color.Red, Color.Green)
                val squarePath = Path()
                val width = 50f

                onDrawBehind {
                    // this section is called during animation
                    val offset = Offset(0f, moveAnimation.value.value)

                    // cannot be outside onDrawBehind because needs to follow square movement
                    val squareBrush = Brush.verticalGradient(
                        colors = colorList,
                        startY = offset.y,
                        endY = offset.y + width
                    )

                    squarePath.reset()
                    // not using drawRect in this example - there can be more complex Path
                    squarePath.apply {
                        moveTo(offset.x, offset.y)
                        relativeLineTo(0f, width)
                        relativeLineTo(width, 0f)
                        relativeLineTo(0f, -width)
                    }

                    drawPath(path = squarePath, brush = squareBrush)
                }
            },
        )
r
Instead of rebuilding the path you could just translate it?
And then you wouldn't need to recreate the gradient every time
m
I was looking into translate but it's not working with gradient (square is moving but gradient not). But even if this is somehow working what should be gradient startY and endY? Below is the edited and not working version.
Copy code
Box(
        modifier = Modifier
            .drawWithCache {
                // this section is cached and not called during animation
                val colorList = listOf(Color.Red, Color.Green)
                val width = 50f

                val squarePath = Path().apply {
                    moveTo(0f, 0f)
                    relativeLineTo(0f, width)
                    relativeLineTo(width, 0f)
                    relativeLineTo(0f, -width)
                }

                val squareBrush = Brush.verticalGradient(
                    colors = colorList,
                    startY = 0f,
                    endY = 0f + width
                )

                onDrawBehind {
                    // this section is called during animation
                    val offset = Offset(0f, moveAnimation.value)
                    squarePath.translate(offset)
                    drawPath(path = squarePath, brush = squareBrush)
                }
            },

        )
r
Dont apply translate to the path itself, translate the drawscope
translate(x, y) { drawPath() }
That’ll translate the gradient as well
m
Yes, you're right. I didn't get it before. It's working. Thank you. Here's working code if anyone is interested.
Copy code
Box(
        modifier = Modifier
            .drawWithCache {
                // this section is cached and not called during animation
                val colorList = listOf(Color.Red, Color.Green)
                val width = 50f
                val squarePath = Path().apply {
                    moveTo(0f, 0f)
                    relativeLineTo(0f, width)
                    relativeLineTo(width, 0f)
                    relativeLineTo(0f, -width)
                }

                val squareBrush = Brush.verticalGradient(
                    colors = colorList,
                    startY = 0f,
                    endY = 0f + width
                )

                onDrawBehind {
                    // this section is called during animation
                    translate(left = 0f, top = moveAnimation.value) {
                        drawPath(path = squarePath, brush = squareBrush)
                    }
                }
            },

        )
r
You also don't need the intermediate Offset variable
m
Correct, I left it before for better "readability". I edited it out now to have correct sample code.