SwiftUI实现Apple Wallet样式卡片:顶部缺口与阴影问题求助
SwiftUI实现带顶部缺口的Wallet样式卡片(支持阴影)
原代码用白色椭圆遮盖背景来模拟缺口的方式,本质是视觉遮挡而非真正的形状裁剪,导致阴影无法适配缺口轮廓——阴影只会围绕整个矩形背景显示,缺口部分的阴影效果完全不对。
正确的做法是自定义一个带缺口的形状,通过clipShape裁剪卡片背景,这样阴影就能完美贴合缺口轮廓:
1. 定义带缺口的卡片形状
struct NotchedCardShape: Shape { let notchWidth: CGFloat let notchHeight: CGFloat func path(in rect: CGRect) -> Path { var path = Path() // 起点:左上角 path.move(to: CGPoint(x: rect.minX, y: rect.minY)) // 绘制到缺口左侧端点 path.addLine(to: CGPoint(x: rect.midX - notchWidth/2, y: rect.minY)) // 绘制半圆形缺口(向下凹陷) path.addArc(center: CGPoint(x: rect.midX, y: rect.minY), radius: notchWidth/2, startAngle: .degrees(180), endAngle: .degrees(0), clockwise: false) // 绘制到右上角 path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY)) // 绘制右侧边 path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) // 右下角圆角 path.addArc(center: CGPoint(x: rect.maxX - 8, y: rect.maxY - 8), radius: 8, startAngle: .degrees(0), endAngle: .degrees(90), clockwise: false) // 绘制底部边 path.addLine(to: CGPoint(x: rect.minX + 8, y: rect.maxY)) // 左下角圆角 path.addArc(center: CGPoint(x: rect.minX + 8, y: rect.maxY - 8), radius: 8, startAngle: .degrees(90), endAngle: .degrees(180), clockwise: false) // 闭合路径回到起点 path.addLine(to: CGPoint(x: rect.minX, y: rect.minY)) return path } }
2. 使用自定义形状构建卡片
struct WalletCardView: View { var body: some View { VStack(alignment: .leading, spacing: 8) { HStack { Spacer() Text("Card") .foregroundColor(.white) Spacer() } .frame(height: 200) // 添加卡片其他内容 Text("Card Details") .foregroundColor(.white) Text("Balance: $100.00") .foregroundColor(.white) } .padding() .frame(maxWidth: .infinity, maxHeight: 300) .background(Color("BuoyPurple")) .clipShape(NotchedCardShape(notchWidth: 60, notchHeight: 25)) // 调整缺口大小 .shadow(color: .black.opacity(0.3), radius: 10, x: 0, y: 5) // 自定义阴影参数 .padding() } }
关键说明
- 自定义
NotchedCardShape精确绘制了带顶部半圆形缺口和底部圆角的轮廓,裁剪后的背景是真正的缺口形状,而非遮盖效果。 - 阴影会自动适配裁剪后的完整形状,完美还原Apple Wallet卡片的阴影质感。
- 可通过修改
notchWidth、notchHeight调整缺口大小,修改圆角半径值调整卡片边角圆润度。
内容的提问来源于stack exchange,提问作者Thom
相关产品推荐
相关产品推荐

