如何在Jetpack Compose中实现卡片角落蓝色曲线设计
在Jetpack Compose中实现带角落蓝色曲线的卡片设计
要实现图中卡片的角落蓝色曲线效果,推荐两种简洁的实现方式,以下是具体代码和说明:
方式一:自定义Shape实现轮廓叠加
通过自定义Shape类定义带曲线的轮廓,再用两层Box叠加实现蓝色曲线露边的效果:
1. 定义自定义Shape
class CornerCurveShape( private val curveRadius: Dp ) : Shape { override fun createOutline( size: Size, layoutDirection: LayoutDirection, density: Density ): Outline { val radius = with(density) { curveRadius.toPx() } val path = Path().apply { // 左上角起点 moveTo(0f, 0f) // 右上角绘制二次贝塞尔曲线 lineTo(size.width - radius, 0f) quadraticBezierTo( x1 = size.width, y1 = 0f, x2 = size.width, y2 = radius ) // 右下角直线 lineTo(size.width, size.height) // 左下角绘制二次贝塞尔曲线 lineTo(radius, size.height) quadraticBezierTo( x1 = 0f, y1 = size.height, x2 = 0f, y2 = size.height - radius ) // 闭合路径 close() } return Outline.Generic(path) } }
2. 封装卡片组件
@Composable fun CurveCornerCard( modifier: Modifier = Modifier, curveRadius: Dp = 24.dp, content: @Composable () -> Unit ) { Box(modifier = modifier.padding(curveRadius / 2)) { // 底层蓝色曲线背景层 Box( modifier = Modifier .matchParentSize() .clip(CornerCurveShape(curveRadius)) .background(Color.Blue) ) // 上层白色内容卡片,通过内边距露出蓝色曲线 Box( modifier = Modifier .matchParentSize() .padding(curveRadius / 2) .clip(RoundedCornerShape(curveRadius / 2)) .background(Color.White) .padding(16.dp) ) { content() } } }
3. 使用示例
@Preview @Composable fun PreviewCurveCard() { CurveCornerCard(curveRadius = 24.dp) { Column { Text("卡片标题", style = MaterialTheme.typography.headlineSmall) Spacer(modifier = Modifier.height(8.dp)) Text("这里是卡片内容区域,可自由添加Compose组件", style = MaterialTheme.typography.bodyMedium) } } }
方式二:Canvas直接绘制曲线
如果不需要整体轮廓裁剪,可直接在卡片背景上用Canvas绘制指定角落的蓝色曲线,更轻量灵活:
@Composable fun CanvasCurveCard( modifier: Modifier = Modifier, curveRadius: Dp = 24.dp, content: @Composable () -> Unit ) { val radius = with(LocalDensity.current) { curveRadius.toPx() } Box( modifier = modifier .background(Color.White) .padding(16.dp) .drawBehind { // 绘制右上角蓝色曲线 drawPath( path = Path().apply { moveTo(size.width - radius, 0f) quadraticBezierTo(size.width, 0f, size.width, radius) lineTo(size.width, 0f) close() }, color = Color.Blue ) // 绘制左下角蓝色曲线 drawPath( path = Path().apply { moveTo(0f, size.height - radius) quadraticBezierTo(0f, size.height, radius, size.height) lineTo(0f, size.height) close() }, color = Color.Blue ) } ) { content() } }
两种方式都可以实现需求,可根据实际场景选择:自定义Shape适合需要卡片整体特殊轮廓的场景,Canvas绘制适合仅局部添加曲线的场景。
内容的提问来源于stack exchange,提问作者Jay Jhaveri
相关产品推荐
相关产品推荐

