我想要添加一个边框到上半部分的卡片组件,它有一个角半径(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相关问答推荐

ENV变量在gradle进程中没有更新

Android设备.Net Maui上的mp3文件列表

关闭导致Kotlin中的内存泄漏?

无法将Kotlin序列化添加到Android项目

Android App Google AdMob";广告加载失败:3;带有测试ID,&q;广告加载失败:1 for My Gahad

在Android中使用Room从SQlite数据库中获取实体列表的正确方式是什么?

在c中更新MVVMCross中TextView的Alpha#

如何显示具体的商品数量?

如何在C++中使用JNI_GetCreatedJavaVMs调用Java代码

Android Jetpack Compose 电视焦点恢复

为一组闪烁的可组合项制作动画,控制同步/定时

如何在Android中使用嵌套的Recyclerview

自定义 Compose Arrangement 以在 LazyRow/LazyColumn 的开头和结尾添加额外的间距

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

有什么方法可以确定正在使用哪个 Android 手机的麦克风进行录音?

是什么让 Android Studio 中的按钮变成紫色?加上新手的其他奇怪行为

如何将新的 ComponentActivity 与 ViewBinding 和其他旧的 AppCompatActivity 组件一起使用

如何在stroke android drawable中设置渐变

Android Wifi-API 在 Android 10+ 上真的那么糟糕吗?

Android 模拟器没有响应 Xamarin 的 AMD 进程的问题