如何在Card顶部居中圆形图片下方绘制弧形?
不用Canvas的简洁解决方案
优先推荐自定义Shape的方式,完全适配Compose原生机制,能让Card边框和头像完美衔接,不会出现线条截断问题:
1. 自定义顶部内凹弧形Shape
创建一个自定义Shape类,在Card顶部中间挖一个和头像匹配的半圆弧形:
class TopCenterCutoutShape(private val cutoutRadius: Dp) : Shape { override fun createOutline( size: Size, layoutDirection: LayoutDirection, density: Density ): Outline { val radius = with(density) { cutoutRadius.toPx() } val path = Path().apply { // 从左上角开始绘制轮廓 moveTo(0f, radius) // 绘制左侧直线到弧形起点 lineTo((size.width / 2) - radius, radius) // 绘制内凹半圆 arcTo( rect = Rect( left = (size.width / 2) - radius, top = 0f, right = (size.width / 2) + radius, bottom = radius * 2 ), startAngleDegrees = 180f, sweepAngleDegrees = 180f, forceMoveTo = false ) // 绘制右侧直线到右下角 lineTo(size.width, radius) lineTo(size.width, size.height) lineTo(0f, size.height) close() } return Outline.Generic(path) } }
2. 修改Card和头像布局
把Card的默认Shape替换成自定义的,同时调整头像位置让它刚好卡在弧形里:
Box(modifier) { Card( modifier = Modifier .fillMaxWidth() .padding(top = 50.dp), // 自定义Shape,cutoutRadius和头像半径一致(头像size100dp,所以设50dp) shape = TopCenterCutoutShape(50.dp), border = BorderStroke(1.dp, Color.LightGray) ) { // Card内部内容,注意加top padding避免被弧形挡住 Box(modifier = Modifier.fillMaxSize().padding(top = 50.dp)) { // ... 原来的Card内部内容 } } Box( modifier = Modifier .fillMaxWidth() // 调整offset让头像刚好嵌入弧形,减去border宽度避免错位 .offset(y = -(50.dp - 1.dp)) .zIndex(2f), contentAlignment = Alignment.TopCenter ) { Image( painter = painterResource(R.drawable.ic_android_black_24dp), contentDescription = "avatar", contentScale = ContentScale.Crop, modifier = Modifier .size(100.dp) .clip(CircleShape) .border(2.dp, Color.LightGray, CircleShape) .background(Color.White) .padding(16.dp) ) } }
备选临时方案(适合快速验证)
如果不想写自定义Shape,可以用同Card背景色的半圆遮挡Card边框:
在头像下方加一个只显示下半圆的Box,zIndex介于Card和头像之间:
Box( modifier = Modifier .fillMaxWidth() .offset(y = 15.dp) .zIndex(1f), contentAlignment = Alignment.TopCenter ) { Box( modifier = Modifier .size(100.dp) .clip(RoundedCornerShape(bottomStart = 50.dp, bottomEnd = 50.dp)) .background(Color.White) // 颜色必须和Card背景一致 ) }
这个方法缺点是依赖固定背景色,不如自定义Shape通用。
内容的提问来源于stack exchange,提问作者Gastón Saillán
相关产品推荐
相关产品推荐

