Вырезание одной формы из другой формы в Jetpack Compose

#kotlin #android-jetpack-compose #android-jetpack-compose-canvas

Вопрос:

У меня был вопрос о создании этого представления в Compose, и я понятия не имею о его реализации.

Вид

Мой текущий код выглядит так:

 Box(
    modifier = Modifier
        .fillMaxSize()
        .height(300.dp)
) {
    Canvas(modifier = Modifier.matchParentSize()) {
        drawRoundRect(
            color = Color.Yellow,
            cornerRadius = CornerRadius(16.dp.toPx(), 16.dp.toPx())
        )
        drawRoundRect(
            color = Color.White,
            topLeft = Offset(
                x = size.width / 5,
                y = size.height - 60.dp.toPx()
            ),
            size = Size((size.width / 5) * 3, 50.dp.toPx() * 2),
            cornerRadius = CornerRadius(24.dp.toPx(), 24.dp.toPx()),
        )
    }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        Text(
            text = "Test",
            modifier = Modifier.align(Alignment.BottomCenter)
        )
    }
}
 

Результатом является следующее:

мой взгляд

Ответ №1:

Чтобы отрезать какой-то путь от другого пути, вы можете использовать clipPath .

А для внешнего радиуса угла вам нужно вручную добавить дуги к контуру, вот так:

 Canvas(modifier = Modifier.matchParentSize()) {
    val outerCornerRadius = 16.dp.toPx()
    val clippedPath = Path().apply {
        val innerCornerRadius = 24.dp.toPx()
        val rectSize = Size(round((size.width / 5) * 3), round(50.dp.toPx() * 2))
        val rect = Rect(
            offset = Offset(
                x = (size.width - rectSize.width) / 2,
                y = size.height - rectSize.height
            ),
            size = rectSize
        )

        addRoundRect(
            RoundRect(
                rect,
                topLeft = CornerRadius(x = innerCornerRadius, y = innerCornerRadius),
                topRight = CornerRadius(x = innerCornerRadius, y = innerCornerRadius),
            )
        )
        val outerCornerDiameter = outerCornerRadius * 2
        val cornerSize = Size(outerCornerDiameter,outerCornerDiameter)
        val cornerOffset = Offset(outerCornerDiameter, outerCornerDiameter)
        val cornerYOffset = Offset(0f, outerCornerDiameter)
        moveTo(rect.bottomLeft - cornerYOffset)
        addArc(
            Rect(
                offset = rect.bottomLeft - cornerOffset,
                size = cornerSize
            ),
            startAngleDegrees = 0f,
            sweepAngleDegrees = 90f,
        )
        lineTo(rect.bottomLeft)

        moveTo(rect.bottomRight - cornerYOffset)
        addArc(
            Rect(
                offset = rect.bottomRight - cornerYOffset,
                size = cornerSize
            ),
            startAngleDegrees = 180f,
            sweepAngleDegrees = -90f,
        )
        lineTo(rect.bottomRight)
    }
    clipPath(clippedPath, clipOp = ClipOp.Difference) {
        drawRoundRect(
            color = Color.Yellow,
            cornerRadius = CornerRadius(outerCornerRadius, outerCornerRadius)
        )
    }
}
 

Результат: