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

如何在Android Jetpack Compose中实现指定曲线视图?

问题:实现指定曲线视图

想要实现下图所示的曲线效果:
目标曲线视图

当前编写了DrawBrackets Composable,但无法得到预期效果,代码如下:

@Composable
fun DrawBrackets() {
    Box(
        modifier = Modifier
            .height(200.dp)
            .width(200.dp)
    ) {

    Canvas(
        modifier = Modifier
            .height(200.dp)
            .width(200.dp)
    ) {
        val width = size.width
        val height = size.height
        val halfWidth = width.times(.5f)
        val halfHeight = height.times(.5f)

        val startPoints = listOf(
            PointF(0f, height),
            PointF(width, height),
        )

        val path = Path().apply {
            startPoints.forEach { point -

                val curveXPart1 =
                    if (point.x > halfWidth)
                        width.minus(halfWidth.times(.5f))
                    else
                        halfWidth.times(.5f)

                val curveXPart2 =
                    if (point.x > halfWidth)
                        width.minus(halfWidth.times(.7f))
                    else
                        halfWidth.times(.7f)

                val curve1 = PointF(curveXPart1, point.y)
                val curve2 = PointF(curveXPart1, halfHeight - ((halfHeight - point.y) / 2))

                moveTo(point.x, point.y)
                quadraticBezierTo(
                    curve1.x,
                    curve1.y,
                    curve2.x,
                    curve2.y,
                )
                quadraticBezierTo(
                    curveXPart1,
                    halfHeight,
                    curveXPart2,
                    halfHeight,
                )
            }
        }
        drawPath(
            path = path,
            color = Color.Black,
            style = Stroke(width = 20f, cap = StrokeCap.Round)
        )
    }
    }
}
解决方案

你的代码存在3个关键问题:

  • 语法错误:startPoints.forEach { point - 应为 startPoints.forEach { point ->
  • 路径构建逻辑错误:循环中重复调用moveTo虽能生成两段曲线,但贝塞尔曲线的控制点、终点计算逻辑完全不符合目标形状
  • 弯曲方向偏差:控制点设置导致曲线无法形成"向上垂直弯曲后水平延伸"的效果

以下是修正后的代码,可完全匹配目标效果:

@Composable
fun DrawBrackets() {
    Box(
        modifier = Modifier
            .height(200.dp)
            .width(200.dp)
    ) {
        Canvas(
            modifier = Modifier.matchParentSize()
        ) {
            val width = size.width
            val height = size.height
            val curveHeight = height * 0.5f // 曲线上升到的高度
            val horizontalExtend = width * 0.2f // 水平向内延伸的长度

            val path = Path().apply {
                // 绘制左侧曲线
                moveTo(0f, height)
                quadraticBezierTo(
                    x1 = 0f,
                    y1 = curveHeight,
                    x2 = horizontalExtend,
                    y2 = curveHeight
                )

                // 绘制右侧曲线
                moveTo(width, height)
                quadraticBezierTo(
                    x1 = width,
                    y1 = curveHeight,
                    x2 = width - horizontalExtend,
                    y2 = curveHeight
                )
            }

            drawPath(
                path = path,
                color = Color.Black,
                style = Stroke(width = 20f, cap = StrokeCap.Round)
            )
        }
    }
}

代码说明

  • 用matchParentSize()让Canvas自动填充父Box尺寸,避免重复设置宽高
  • 左侧曲线从左下角(0, height)出发,控制点设为(0, curveHeight),终点为(horizontalExtend, curveHeight),形成"垂直向上弯后水平向右"的形状
  • 右侧曲线逻辑对称,从右下角出发向上弯曲后水平向左延伸
  • 可通过调整curveHeight和horizontalExtend参数,适配不同的尺寸需求

内容的提问来源于stack exchange,提问作者Ishika Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 12:59:14