You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jetpack Compose中绘制自定义圆角内凹圆形?

在Jetpack Compose中绘制右侧内凹的圆角图形

因为RoundedCornerShape不支持负半径,要实现右侧内凹的效果,你需要自定义Shape,通过Path手动绘制路径:

1. 自定义内凹Shape

实现Shape接口,在createOutline方法中构建符合需求的路径:

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp

class InnerConcaveCircleShape(private val concaveRadius: Float = 20.dp.toPx()) : Shape {
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        val path = Path()
        val width = size.width
        val height = size.height
        // 左侧圆角半径(取高度一半,保证左右两侧为圆弧轮廓)
        val cornerRadius = height / 2

        // 起点:左上角圆角的结束点
        path.moveTo(cornerRadius, 0f)

        // 绘制左上方圆角
        path.arcTo(
            rect = Rect(0f, 0f, cornerRadius * 2, cornerRadius * 2),
            startAngleDegrees = 90f,
            sweepAngleDegrees = 90f,
            forceMoveTo = false
        )

        // 绘制左侧底边到左下角圆角
        path.lineTo(0f, height - cornerRadius)

        // 绘制左下角圆角
        path.arcTo(
            rect = Rect(0f, height - cornerRadius * 2, cornerRadius * 2, height),
            startAngleDegrees = 180f,
            sweepAngleDegrees = 90f,
            forceMoveTo = false
        )

        // 绘制底边到右下角内凹起始点
        path.lineTo(width - concaveRadius, height)

        // 绘制右侧内凹圆弧(从右下角顺时针到右上角)
        path.arcTo(
            rect = Rect(width - concaveRadius * 2, height / 2 - concaveRadius, width, height / 2 + concaveRadius),
            startAngleDegrees = 90f,
            sweepAngleDegrees = -180f,
            forceMoveTo = false
        )

        // 绘制顶边回到起点,闭合路径
        path.lineTo(cornerRadius, 0f)
        path.close()

        return Outline.Generic(path)
    }
}

2. 在Compose中使用自定义Shape

可以通过两种方式应用这个Shape:

示例1:用clip裁剪布局

Box(
    modifier = Modifier
        .size(120.dp)
        .clip(InnerConcaveCircleShape(concaveRadius = 30.dp.toPx()))
        .background(Color.Blue)
)

示例2:直接在Canvas绘制图形

Canvas(modifier = Modifier.size(120.dp)) {
    drawPath(
        path = InnerConcaveCircleShape(30.dp.toPx()).createOutline(size, LayoutDirection.Ltr, this).path,
        color = Color.Blue
    )
}

关键说明

  • concaveRadius参数控制右侧内凹的程度,值越大内凹越明显
  • 左侧圆角半径取高度一半,保证整体趋近圆形轮廓,你可以根据需求调整这个值
  • arcTo的sweepAngleDegrees设为负数时,会沿顺时针方向绘制圆弧,刚好实现内凹效果

内容的提问来源于stack exchange,提问作者Pranav P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 06:52:11