Search code examples
androidcanvasdrawandroid-jetpack-composeshadow

How can I draw a shadow for a path in canvas in jetpack compose


I am drawing a custom shape for a topbar in jetpack compose. I want to draw a shadow for the path.

val topBarShapePath = Path().apply {
    moveTo(dpToPixels(leftPadding), 0f)
    lineTo(dpToPixels(leftPadding), dpToPixels(dpValue = 110.dp))
    arcTo(
        Rect(
            dpToPixels(leftPadding),
            dpToPixels(dpValue = 110.dp),
            dpToPixels(dpValue = 32.dp),
            dpToPixels(dpValue = 135.dp)
        ), 
        -180f, -90f, true
    )
    lineTo(
        dpToPixels(dpValue = triangleStartX),
        dpToPixels(dpValue = rectHeight)
    )
    lineTo(
        dpToPixels(dpValue = screenWidth),
        dpToPixels(dpValue = triangleEndY)
    )
    lineTo(dpToPixels(dpValue = screenWidth), 0f)
    lineTo(dpToPixels(dpValue = leftPadding), 0f)
}
        
Column(
    modifier = Modifier
        .fillMaxWidth()
        .height(400.dp)
        .drawBehind {
            val finalWidth = 40.dp.toPx()
            drawPath(
                topBarShapePath,
                color = topbarcolor
            )
            drawOutline(
                outline = Outline.Generic(topBarShapePath),
                brush = Brush.horizontalGradient(),
                style = Stroke(width = 1.dp.toPx())
            )
        }
)

This is the code I am using to draw the shape, the "drawOutline" was to try and draw a shadow for the path, but I can't figure out how to blur the line.

Any help appreciated.

Here is a screenshot of the result I am looking for: Image of result


Solution

  • It's impossible to draw shadow in Canvas at the moment, but you can do it with Modifier.shadow, specifying the needed custom shape, like this:

    class TopBarShape(/*some parameters*/): Shape {
        override fun createOutline(
            size: Size,
            layoutDirection: LayoutDirection,
            density: Density,
        ) = Outline.Generic(Path().apply {
            // your path code
        })
    }
    
    Modifier.shadow(elevation = 10.dp, shape = TopBarShape(/*your parameters*/))
    

    Sadly this modifier doesn't allow much modifications, it's one of the most starred Compose issues, so hopefully it'll change in future, but as it's not in the latest 1.1-beta I wouldn't expect it at least until 1.2.

    If you still think that drawing shadow manually is a needed feature, you can create a feature request.