我想要添加一个边框到上半部分的卡片组件,它有一个角半径(10dp). 因此,只有底牌的底部缺失,其余部分的冲程为1DP.(有点像U形和倒U形)

我想对底角半径和顶部缺失的卡片做同样的处理.

我试着设计一个定制的形状,但它不尊重卡片的形状.

// this is just a line but it doesn't respect the card corner radius? 

private fun createShape(thickness: Float) : Shape {
    return GenericShape { size, _ ->
        moveTo(0f,0f)
        lineTo(0f, size.height)
        lineTo(thickness, size.height)
        lineTo(thickness, 0f)
        lineTo(0f, thickness)
    }
}


val thickness = with(LocalDensity.current) {
    1.dp.toPx()
}
Card(
    shape = RoundedCornerShape(topEnd = 10.dp, topStart = 10.dp, bottomEnd = 0.dp, bottomStart = 0.dp),
    modifier = Modifier
        .border(BorderStroke(width = 1.dp, color = Color.Black), createShape(thickness))

) {
    ...
}

推荐答案

边框似乎不允许打开的形状,强制形状关闭,即使你画了3条线,因为你需要使用Modifier.draBehind或Modifier.draWithContent.

enter image description here

创建了一个Modifier,将U形边框绘制为

fun Modifier.semiBorder(strokeWidth: Dp, color: Color, cornerRadiusDp: Dp) = composed(
    factory = {
        val density = LocalDensity.current
        val strokeWidthPx = density.run { strokeWidth.toPx() }
        val cornerRadius = density.run { cornerRadiusDp.toPx() }

        Modifier.drawBehind {
            val width = size.width
            val height = size.height

            drawLine(
                color = color,
                start = Offset(x = 0f, y = height),
                end = Offset(x = 0f, y = cornerRadius),
                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 = cornerRadius, 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 = height),
                end = Offset(x = width, y = cornerRadius),
                strokeWidth = strokeWidthPx
            )
        }
    }
)

用法

@Composable
private fun UShapeBorderSample() {
    Card(
        shape = RoundedCornerShape(
            topEnd = 10.dp,
            topStart = 10.dp,
            bottomEnd = 0.dp,
            bottomStart = 0.dp
        ),
        modifier = Modifier
            .semiBorder(1.dp, Color.Black, 10.dp)

    ) {
        Box(
            modifier = Modifier
                .size(150.dp)
                .background(Color.White),
            contentAlignment = Alignment.Center
        ) {
            Text("Hello World")
        }
    }

    Spacer(modifier = Modifier.height(10.dp))

    Card(
        shape = RoundedCornerShape(
            topEnd = 20.dp,
            topStart = 20.dp,
            bottomEnd = 0.dp,
            bottomStart = 0.dp
        ),
        modifier = Modifier
            .semiBorder(1.dp, Color.Black, 20.dp)

    ) {
        Box(
            modifier = Modifier
                .size(150.dp)
                .background(Color.White),
            contentAlignment = Alignment.Center
        ) {
            Text("Hello World")
        }
    }
}

您需要使用圆弧来创建圆角.在创建形状时,不是传递厚度,而是传递形状半径.绘制边框时需要厚度.您绘制的是一个宽度为1.dp的矩形.

enter image description here

@Composable
private fun createShape(cornerRadius: Dp): Shape {

    val density = LocalDensity.current
    return GenericShape { size, _ ->

        val width = size.width
        val height = size.height
        val cornerRadiusPx = density.run { cornerRadius.toPx() }

        moveTo(0f, height)

        // Vertical line on left size
        lineTo(0f, cornerRadiusPx * 2)

        arcTo(
            rect = Rect(
                offset = Offset.Zero,
                size = Size(cornerRadiusPx * 2, cornerRadiusPx * 2)
            ),
            startAngleDegrees = 180f,
            sweepAngleDegrees = 90f,
            forceMoveTo = false
        )

        lineTo(width - cornerRadiusPx * 2, 0f)
        arcTo(
            rect = Rect(
                offset = Offset(width - cornerRadiusPx * 2, 0f),
                size = Size(cornerRadiusPx * 2, cornerRadiusPx * 2)
            ),
            startAngleDegrees = 270f,
            sweepAngleDegrees = 90f,
            forceMoveTo = false
        )
        // Vertical line on right size
        lineTo(width, height)

    }
}

用法

@Composable
private fun UShapeBorderSample() {
    Card(
        shape = RoundedCornerShape(
            topEnd = 10.dp,
            topStart = 10.dp,
            bottomEnd = 0.dp,
            bottomStart = 0.dp
        ),
        modifier = Modifier
            .border(BorderStroke(width = 1.dp, color = Color.Black), createShape(10.dp))

    ) {
        Box(modifier = Modifier
            .size(200.dp)
            .background(Color.White),
            contentAlignment = Alignment.Center
        ) {
            Text("Hello World")
        }
    }
}

边框不尊重形状,因为它是一幅图,但Card是引擎盖下的Box,它使用Shape,Modifier.clip()本身就是Modifier.graphicsLayer{clip},它在一个层上应用操作.

您可以查看关于剪辑和边框的不同之处的答案.

https://stackoverflow.com/a/73091667/5457853

Android相关问答推荐

Android添加设置图标齿轮到应用程序信息

Android意图过滤器不限制应用程序仅处理YouTube链接

Android可绘制边框删除底线

如何在使用带有底部导航组件的片段管理器时更改片段工具栏的标签

如何检测低性能 Android 设备进行条件动画渲染?

为什么我在 android 中使用 TabLayout 时无法启动我的 Activity?

Kotlin - 在继续之前如何等待这个协程完成?

expo 上的 socket.io 无法从 Android 连接

为什么 Android Studio 中的 theme.xml 目录没有任何原色

Material 3的MaterialSwitch默认大小太大了?如何使它变小?

将 React Native 应用程序背景带到前台

Jetpack Compose 绘制范围内的动画

具有管理员权限的 Kotlin 中的多用户系统

在 kotlin 中动态添加 GridView

DatePickerDialog (Android/Kotlin) 的两个问题

为什么我的应用程序使用这些信息?

Android apk 不工作

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

协程是否在 if 条件下保持秩序?

EAS 构建失败,错误代码为 1,但 Expo Build 成功,我需要 EAS 构建来删除未使用的包,如 com.segment.analytics.android:analytics