Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating cutout notch in android jetpack compose

enter image description here

I wanted to create a ticket type layout with notch & cutout. also shadow like second image Want to know the at least the start point since I am new in compose.

enter image description here

I wanted to create a ticket type layout with notch & cutout. Want to know the at least the start point since I am new in compose.

like image 219
T_V Avatar asked Dec 02 '25 22:12

T_V


1 Answers

The key trick here is to use offscreen composition strategy and DST_OUT blend mode.

Quick-and-dirty implementation:

@Composable
fun App() {
    Box(
        modifier = Modifier.fillMaxSize().background(linearGradient(listOf(Color.White, Color.Blue)))
    ) {
        Ticket(
            numberOfHoles = 7, brush = linearGradient(
                listOf(
                    Color(0.7f, 0f, 1f), Color(0.4f, 0f, 1f)
                )
            ), modifier = Modifier.align(Alignment.Center).size(width = 300.dp, height = 200.dp)
        )
    }
}

@Composable
fun Ticket(
    numberOfHoles: Int = 7, brush: Brush, modifier: Modifier = Modifier
) {
    Box(modifier = modifier) {
        Canvas(
            modifier = modifier.fillMaxSize().graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen }
        ) {
            val cornerRadius = size.minDimension / 8f
            val holeRadius = size.minDimension / 30f
            drawRect(brush = brush)
            drawCircle(
                color = Color(0xFFFFFFFF),
                center = Offset(x = 0f, y = 0f),
                radius = cornerRadius,
                blendMode = BlendMode.DstOut
            )
            drawCircle(
                color = Color(0xFFFFFFFF),
                center = Offset(x = 0f, y = size.height),
                radius = cornerRadius,
                blendMode = BlendMode.DstOut
            )
            drawCircle(
                color = Color(0xFFFFFFFF),
                center = Offset(x = size.width, y = size.height),
                radius = cornerRadius,
                blendMode = BlendMode.DstOut
            )
            drawCircle(
                color = Color(0xFFFFFFFF),
                center = Offset(x = size.width, y = 0f),
                radius = cornerRadius,
                blendMode = BlendMode.DstOut
            )
            drawCircle(
                color = Color(0xFFFFFFFF),
                center = Offset(x = size.width, y = 0f),
                radius = cornerRadius,
                blendMode = BlendMode.DstOut
            )

            val holeStart = cornerRadius * 2
            val holeEnd = size.width - cornerRadius * 2
            val totalSpace = holeEnd - holeStart
            val elementSize = holeRadius * 2
            val numOfSpaces = numberOfHoles - 1
            val space = (totalSpace - (numberOfHoles * elementSize)) / numOfSpaces

            for (i in 0..<numberOfHoles) {
                drawCircle(
                    color = Color(0xFFFFFFFF),
                    center = Offset(
                        x = holeStart + holeRadius + (space + holeRadius * 2) * i,
                        y = cornerRadius / 2
                    ),
                    radius = holeRadius,
                    blendMode = BlendMode.DstOut
                )
                drawCircle(
                    color = Color(0xFFFFFFFF),
                    center = Offset(
                        x = holeStart + holeRadius + (space + holeRadius * 2) * i,
                        y = size.height
                    ),
                    radius = holeRadius,
                    blendMode = BlendMode.DstOut
                )
            }
        }
    }
}

Yields this result with transparent cutouts:
enter image description here

like image 152
Ilya E Avatar answered Dec 05 '25 10:12

Ilya E



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!