CookieMonster
CookieMonster

Reputation: 856

Jetpack Compose: how to cut out card shape?

I want to create a half-transparent layer above the camera preview, like this:

enter image description here

I have the camera preview done in my app, all I want is a half-transparent layer over my preview with a cut-out card shape, like in the picture (with rounded corners).

So: fullscreen camera preview, on top of that there is a full screen half-transparent overlay, in which there is a card-shaped hole cut out

How can I do this?

Upvotes: 3

Views: 2156

Answers (1)

Thracian
Thracian

Reputation: 67218

You can use BlendModes to exclude a Rectangle from a transparent layer using

@Composable
private fun TransparentCamLayout() {
    Box(
        modifier = Modifier
            .fillMaxSize()
            .drawWithContent {

                val canvasWidth = size.width
                val canvasHeight = size.height
                val width = canvasWidth * .9f
                val height = width * 3 / 4f

                drawContent()

                drawWithLayer {

                    // Destination
                    // This is transparent color
                    drawRect(Color(0x99000000))

                    // Source
                    // This is where we extract this rect from transparent
                    drawRect(
                        topLeft = Offset((canvasWidth - width) / 2, canvasHeight * .3f),
                        size = Size(width, height),
                        color = Color.Transparent,
                        blendMode = BlendMode.SrcIn
                    )
                }

                drawRect(
                    topLeft = Offset((canvasWidth - width) / 2, canvasHeight * .3f),
                    size = Size(width, height),
                    color = Color.White,
                    style = Stroke(2.dp.toPx())
                )
            }
    ) {
        Image(
            modifier = Modifier.fillMaxSize(),
            painter = painterResource(id = R.drawable.landscape5),
            contentScale = ContentScale.Crop,
            contentDescription = null
        )
    }
}

/**
 * Draw with layer to use [BlendMode]s
 */
private fun DrawScope.drawWithLayer(block: DrawScope.() -> Unit) {
    with(drawContext.canvas.nativeCanvas) {
        val checkPoint = saveLayer(null, null)
        block()
        restoreToCount(checkPoint)
    }
}

Result

enter image description here

In this tutorial's BlendMode section you can find other usages. As in this answer for custom clipping, building a rating bar and there are many usages limited with your imagination. Blend or PorterDuff modes are very functional for building custom clipping, alpha blending or pixel manipulation.

Upvotes: 6

Related Questions