我正在try 绘制部分或单边开放的矩形圆角边框以实现此效果:

enter image description here

在玩了一会儿之后,我得到了这个:

enter image description here

这可以通过以下方式完成:

RoundedCornerShape(topStartPercent = 50, bottomStartPercent = 50) // start
RoundedCornerShape(topEndPercent = 50, bottomEndPercent = 50) // end
RectangleShape // for middle

我想要的是删除单元格之间的连接垂直线.

推荐答案

您可以使用Modifier.draBehind在Composables后面绘制边框,并判断您的Composable是在开始、中心还是结尾

enum class BorderOrder {
    Start, Center, End
}

fun Modifier.drawSegmentedBorder(
    strokeWidth: Dp,
    color: Color,
    cornerPercent: Int,
    borderOrder: BorderOrder,
    drawDivider: Boolean = false
) = composed(
    factory = {

        val density = LocalDensity.current
        val strokeWidthPx = density.run { strokeWidth.toPx() }

        Modifier.drawBehind {
            val width = size.width
            val height = size.height
            val cornerRadius = height * cornerPercent / 100

            when (borderOrder) {
                BorderOrder.Start -> {

                    drawLine(
                        color = color,
                        start = Offset(x = width, y = 0f),
                        end = Offset(x = cornerRadius, y = 0f),
                        strokeWidth = strokeWidthPx
                    )

                    // Top left arc
                    drawArc(
                        color = color,
                        startAngle = 180f,
                        sweepAngle = 90f,
                        useCenter = false,
                        topLeft = Offset.Zero,
                        size = Size(cornerRadius * 2, cornerRadius * 2),
                        style = Stroke(width = strokeWidthPx)
                    )
                    drawLine(
                        color = color,
                        start = Offset(x = 0f, y = cornerRadius),
                        end = Offset(x = 0f, y = height - cornerRadius),
                        strokeWidth = strokeWidthPx
                    )
                    // Bottom left arc
                    drawArc(
                        color = color,
                        startAngle = 90f,
                        sweepAngle = 90f,
                        useCenter = false,
                        topLeft = Offset(x = 0f, y = height - 2 * cornerRadius),
                        size = Size(cornerRadius * 2, cornerRadius * 2),
                        style = Stroke(width = strokeWidthPx)
                    )
                    drawLine(
                        color = color,
                        start = Offset(x = cornerRadius, y = height),
                        end = Offset(x = width, y = height),
                        strokeWidth = strokeWidthPx
                    )
                }
                BorderOrder.Center -> {
                    drawLine(
                        color = color,
                        start = Offset(x = 0f, y = 0f),
                        end = Offset(x = width, y = 0f),
                        strokeWidth = strokeWidthPx
                    )
                    drawLine(
                        color = color,
                        start = Offset(x = 0f, y = height),
                        end = Offset(x = width, y = height),
                        strokeWidth = strokeWidthPx
                    )

                    if (drawDivider) {
                        drawLine(
                            color = color,
                            start = Offset(x = 0f, y = 0f),
                            end = Offset(x = 0f, y = height),
                            strokeWidth = strokeWidthPx
                        )
                    }
                }
                else -> {

                    if (drawDivider) {
                        drawLine(
                            color = color,
                            start = Offset(x = 0f, y = 0f),
                            end = Offset(x = 0f, y = height),
                            strokeWidth = strokeWidthPx
                        )
                    }

                    drawLine(
                        color = color,
                        start = Offset(x = 0f, y = 0f),
                        end = Offset(x = width - cornerRadius, y = 0f),
                        strokeWidth = strokeWidthPx
                    )

                    // Top right arc
                    drawArc(
                        color = color,
                        startAngle = 270f,
                        sweepAngle = 90f,
                        useCenter = false,
                        topLeft = Offset(x = width - cornerRadius * 2, y = 0f),
                        size = Size(cornerRadius * 2, cornerRadius * 2),
                        style = Stroke(width = strokeWidthPx)
                    )
                    drawLine(
                        color = color,
                        start = Offset(x = width, y = cornerRadius),
                        end = Offset(x = width, y = height - cornerRadius),
                        strokeWidth = strokeWidthPx
                    )
                    // Bottom right arc
                    drawArc(
                        color = color,
                        startAngle = 0f,
                        sweepAngle = 90f,
                        useCenter = false,
                        topLeft = Offset(
                            x = width - 2 * cornerRadius,
                            y = height - 2 * cornerRadius
                        ),
                        size = Size(cornerRadius * 2, cornerRadius * 2),
                        style = Stroke(width = strokeWidthPx)
                    )
                    drawLine(
                        color = color,
                        start = Offset(x = 0f, y = height),
                        end = Offset(x = width -cornerRadius, y = height),
                        strokeWidth = strokeWidthPx
                    )
                }
            }
        }
    }
)

用法

@Composable
private fun SegmentedBorderSample() {
    Row {
        repeat(3) {

            val order = when (it) {
                0 -> BorderOrder.Start
                2 -> BorderOrder.End
                else -> BorderOrder.Center
            }

            Box(
                contentAlignment = Alignment.Center,
                modifier = Modifier
                    .size(40.dp)
                    .drawSegmentedBorder(
                        strokeWidth = 2.dp,
                        color = Color.Green,
                        borderOrder = order,
                        cornerPercent = 40,
                        drawDivider = false
                    )
                    .padding(4.dp)
            ) {
                Text(text = "$it")
            }
        }
    }


    Row {
        repeat(4) {

            val order = when (it) {
                0 -> BorderOrder.Start
                3 -> BorderOrder.End
                else -> BorderOrder.Center
            }

            Box(
                contentAlignment = Alignment.Center,
                modifier = Modifier
                    .size(40.dp)
                    .drawSegmentedBorder(
                        strokeWidth = 2.dp,
                        color = Color.Cyan,
                        borderOrder = order,
                        cornerPercent = 50,
                        drawDivider = true
                    )
                    .padding(4.dp)
            ) {
                Text(text = "$it")
            }
        }
    }
}

结果

enter image description here

Android相关问答推荐

无法列出目录中的文件'

理解修饰符<;方法>;与修饰符<;方法>;:效果和行为解释(Android开发者Jetpack Compose)

安卓Gradle看不到dagger 柄

Android和Rust,OpenSSL交叉编译在ARM V7上链接失败

第一次使用onBackPressed()、NavigateUp()加载时MapView崩溃

Android 14预测性背部手势-闪烁的白色背景色

升级到 Jetpack Compose 物料 list 2023.08.00 需要我将 targetSdk 更改为 34

使用不同的gradle文件导入外部库

Android Studio 在 list 文件中已经声明了活动类,但仍出现无法找到明确的活动类的错误

java.lang.ExceptionInInitializerError -- 原因:java.lang.NullPointerException

如何绘制内边框?

Android Studio电鳗:javaHome好像无效

如何解决 compose 中material 图标的由于接收器类型不匹配,以下候选者都不适用

Jetpack Compose 中的滑动按钮菜单

Compose Accompaniist Pager 中的 TabRow/Tab 重组问题

可组合的可见性不随状态变化而变化

调用时 listFiles() nullpointerexception

为什么我不能直接记住 mutableStateOf 可组合函数?

如何在 MAUI 项目中包含每个平台的现有 C++ 库?

如何在 Jetpack Compose 中禁用 TabRow 或 Tab 中的涟漪效应?