在 Jetpack Compose 中从另一个形状切割一个形状

Cutting one shape from an other shape in Jetpack Compose

我对在 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)
        )
    }
}

结果如下:

要从另一条路径中截取一些路径,您可以使用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)
        )
    }
}

结果: