kotlin 在Jetpack合成中从一个形状剪切另一个形状

4xrmg8kj  于 2023-01-05  发布在  Kotlin
关注(0)|答案(2)|浏览(177)

关于在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)
        )
    }
}

结果如下:

ecfsfe2w

ecfsfe2w1#

要从其他路径剪切某个路径,可以使用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)
        )
    }
}

结果:

fquxozlt

fquxozlt2#

你也可以使用一个自定义的Shape给你的合成对象一个特定的轮廓,只需要扩展Shape接口并覆盖createOutline()方法。

    • 示例:**

对于角,PathAPI提供了一个函数arcTo(),然后使用lineTo()方法绘制形状的边缘。

class RoundedRectOutlinedCorner(
    private val cornerRadius: Dp = 16.dp,
    private val cutOutHeight: Dp = 60.dp,
    private val cutOutWidth: Dp = 145.dp
) : Shape {
    override fun createOutline(
        size: Size, layoutDirection: LayoutDirection, density: Density
    ): Outline {
        return Outline.Generic(Path().apply {
            val cornerRadius = with(density) { cornerRadius.toPx() }
            val cutOutHeight = with(density) { cutOutHeight.toPx() }
            val cutOutWidth = with(density) { cutOutWidth.toPx() }

            arcTo(
                rect = Rect(offset = Offset(0f, 0f), Size(cornerRadius, cornerRadius)),
                startAngleDegrees = 180f,
                sweepAngleDegrees = 90f,
                forceMoveTo = false
            )

            lineTo(size.width - cutOutWidth - cornerRadius, 0f)
            arcTo(
                rect = Rect(
                    offset = Offset(size.width - cutOutWidth - cornerRadius, 0f),
                    Size(cornerRadius, cornerRadius)
                ), startAngleDegrees = 270.0f, sweepAngleDegrees = 90f, forceMoveTo = false
            )

            lineTo(size.width - cutOutWidth, cutOutHeight - cornerRadius)
            arcTo(
                rect = Rect(
                    offset = Offset(size.width - cutOutWidth, cutOutHeight - cornerRadius),
                    Size(cornerRadius, cornerRadius)
                ), startAngleDegrees = 180.0f, sweepAngleDegrees = -90f, forceMoveTo = false
            )

            lineTo(size.width - cornerRadius, cutOutHeight)
            arcTo(
                rect = Rect(
                    offset = Offset(size.width - cornerRadius, cutOutHeight),
                    Size(cornerRadius, cornerRadius)
                ), startAngleDegrees = 270f, sweepAngleDegrees = 90f, forceMoveTo = false
            )

            lineTo(size.width, size.height - cornerRadius)
            arcTo(
                rect = Rect(
                    offset = Offset(size.width - cornerRadius, size.height - cornerRadius),
                    Size(cornerRadius, cornerRadius)
                ), startAngleDegrees = 0f, sweepAngleDegrees = 90f, forceMoveTo = false
            )

            lineTo(cornerRadius, size.height)
            arcTo(
                rect = Rect(
                    offset = Offset(0f, size.height - cornerRadius),
                    Size(cornerRadius, cornerRadius)
                ), startAngleDegrees = 90f, sweepAngleDegrees = 90f, forceMoveTo = false
            )
            close()
        })
    }
}
    • 用法:**然后,您可以使用以下命令剪切形状:
Modifier
    .height(250.dp)
    .clip(RoundedRectOutlinedCorner()),

或使用. graphics图层/.背景等。

    • 结果:**

相关问题