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

Jetpack Compose实现顶部圆角底部票券样式图片的问题

问题描述

我在Jetpack Compose项目里需要实现一张顶部为圆角、底部为票券样式的图片。作为Compose新手,我跟着教程学习,但不知道怎么实现顶部圆角效果。当前代码如下:

class TicketBottom : Shape {
override fun createOutline(
    size: Size,
    layoutDirection: LayoutDirection,
    density: Density
): Outline {
    val cornerRadius = 25f

    val path = Path().apply {
        // Top left arc
        arcTo(
            rect = Rect(
                left = cornerRadius,
                top = cornerRadius,
                right = 0f,
                bottom = 0f
            ),
            startAngleDegrees = 90.0f,
            sweepAngleDegrees = -90.0f,
            forceMoveTo = false
        )
        lineTo(x = size.width - cornerRadius, y = 0f)
        // Top right arc
        arcTo(
            rect = Rect(
                left = size.width + cornerRadius,
                top = -cornerRadius,
                right = size.width + cornerRadius,
                bottom = cornerRadius
            ),
            startAngleDegrees = 180.0f,
            sweepAngleDegrees = -90.0f,
            forceMoveTo = false
        )
        lineTo(x = size.width, y = size.height - cornerRadius)
        // Bottom right arc
        arcTo(
            rect = Rect(
                left = size.width - cornerRadius,
                top = size.height - cornerRadius,
                right = size.width + cornerRadius,
                bottom = size.height + cornerRadius
            ),
            startAngleDegrees = 270.0f,
            sweepAngleDegrees = -90.0f,
            forceMoveTo = false
        )
        lineTo(x = cornerRadius, y = size.height)
        // Bottom left arc
        arcTo(
            rect = Rect(
                left = -cornerRadius,
                top = size.height - cornerRadius,
                right = cornerRadius,
                bottom = size.height + cornerRadius
            ),
            startAngleDegrees = 0.0f,
            sweepAngleDegrees = -90.0f,
            forceMoveTo = false
        )
        lineTo(x = 0f, y = cornerRadius)
    }
    return Outline.Generic(path = path)
}

当前效果截图

解决方案

你的代码里顶部圆角的arcTo参数设置有误,导致圆角未正确生成。调整顶部圆角的路径参数,同时将底部改为票券缺口样式,修改后的代码如下:

class TicketShape : Shape {
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        val topCornerRadius = 25f
        val bottomGapRadius = 15f // 底部票券缺口的半径

        val path = Path().apply {
            // 顶部左圆角
            moveTo(topCornerRadius, 0f)
            arcTo(
                rect = Rect(
                    left = 0f,
                    top = 0f,
                    right = topCornerRadius * 2,
                    bottom = topCornerRadius * 2
                ),
                startAngleDegrees = 180.0f,
                sweepAngleDegrees = 90.0f,
                forceMoveTo = false
            )
            // 顶部右圆角
            lineTo(size.width - topCornerRadius, 0f)
            arcTo(
                rect = Rect(
                    left = size.width - topCornerRadius * 2,
                    top = 0f,
                    right = size.width,
                    bottom = topCornerRadius * 2
                ),
                startAngleDegrees = 270.0f,
                sweepAngleDegrees = 90.0f,
                forceMoveTo = false
            )
            // 右侧边到底部缺口位置
            lineTo(size.width, size.height - bottomGapRadius)
            // 底部右缺口(半圆)
            arcTo(
                rect = Rect(
                    left = size.width - bottomGapRadius * 2,
                    top = size.height - bottomGapRadius,
                    right = size.width,
                    bottom = size.height + bottomGapRadius
                ),
                startAngleDegrees = 0.0f,
                sweepAngleDegrees = 180.0f,
                forceMoveTo = false
            )
            // 底部中间横线
            lineTo(bottomGapRadius * 2, size.height)
            // 底部左缺口(半圆)
            arcTo(
                rect = Rect(
                    left = 0f,
                    top = size.height - bottomGapRadius,
                    right = bottomGapRadius * 2,
                    bottom = size.height + bottomGapRadius
                ),
                startAngleDegrees = 180.0f,
                sweepAngleDegrees = 180.0f,
                forceMoveTo = false
            )
            // 左侧边回到顶部圆角起点
            lineTo(0f, topCornerRadius)
            close()
        }
        return Outline.Generic(path = path)
    }
}

关键修改说明

  • 顶部圆角修正:调整arcTo的矩形范围,确保矩形完全覆盖圆角区域,同时修改起始角度和扫过角度,让圆角正确显示在左上角和右上角。
  • 底部票券缺口实现:将原底部圆角替换为左右两个半圆缺口,通过绘制180度半圆模拟票券的锯齿效果。
  • 路径闭合:添加close()方法确保路径完全闭合,避免绘制异常。

使用示例

在Compose中将该Shape应用到Image或Box的shape参数即可:

Image(
    painter = painterResource(id = R.drawable.your_image),
    contentDescription = "票券图片",
    modifier = Modifier
        .size(300.dp, 400.dp)
        .clip(TicketShape())
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:53:12