我正在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相关问答推荐

如何使用视图模型触发可变状态?

如何使用Gradle风味在两个Kotlin导入(Google vs Amazon Java billing library)之间进行 Select ?

Kotlin Gzip字符串未按预期工作

原因平滑滚动的滞后懒惰列在android jetpack compose

Android Studio -未显示布局预览(不推荐使用安全管理器)

格雷德的两个星号是什么意思?非路径

在Android Studio中,如何在BuildSrc Dependenices Kotlin文件中指定时标记与旧版本的依赖关系

不能有意地从一个活动的可组合功能转移到另一个活动

任务:app:kaptGenerateStubsDebugKotlin执行失败. > 'compileDebugJavaWithJavac' 任务(当前目标是 1.8)

是否可以按照干净的体系 struct 将活动实例传递给视图模型

如何将一个 Composable 作为其参数传递给另一个 Composable 并在 Jetpack Compose 中显示/运行它

Jetpack 组合千位分隔符视觉转换,也适用于小数

观察软键盘可见性,打开/关闭 Jetpack Compose

处理程序 postDelayed 方法不起作用,kotlin 应用程序卡在启动画面上

如何在屏幕旋转或系统主题更改后将光标移动到 TextField 的末尾并保持键盘显示?

获取模板向导配方类 Intellij 中的应用程序包名称

如何处理 com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: For input string: "T1V 4Y8" Kotlin

Firebase Crashlytics 缩小 R8 Android

Jetpack Compose Tapjacking:过滤对模糊 UI 的touch

实际类型别名ApplicationContext没有相应的预期声明