iOS开发:如何实现各边角半径不同的带阴影Card View?
实现四个边角半径各不相同的Card View
你遇到的问题很常见——UIBezierPath(roundedRect:byRoundingCorners:cornerRadii:)这个方法只能给一组边角设置相同的半径,没法单独给四个角指定不同的值,所以你之前的代码只改了一个角,效果自然不对。要实现四个角各不同的圆角,我们需要手动构建完整的贝塞尔路径,同时还要保证阴影能正确匹配这个自定义圆角路径。
下面是完整的解决方案,我把四个角的半径都做成@IBInspectable属性,这样你可以直接在Storyboard里可视化调整每个角的数值:
import UIKit class CustomCornerCard: UIView { // 四个角的独立半径,支持IB可视化编辑 @IBInspectable var topLeftRadius: CGFloat = 0 @IBInspectable var topRightRadius: CGFloat = 0 @IBInspectable var bottomLeftRadius: CGFloat = 0 @IBInspectable var bottomRightRadius: CGFloat = 0 // 阴影相关属性,保留你原来的配置 @IBInspectable var shadowOffsetWidth: Int = 0 @IBInspectable var shadowOffsetHeight: Int = 3 @IBInspectable var shadowColor: UIColor? = .gray @IBInspectable var shadowOpacity: Float = 0.5 override func layoutSubviews() { super.layoutSubviews() // 1. 创建自定义圆角路径 let path = UIBezierPath() let bounds = self.bounds // 从右上圆角的起点开始(顺时针绘制) path.move(to: CGPoint(x: bounds.maxX - topRightRadius, y: bounds.minY)) // 右上圆角 path.addArc(withCenter: CGPoint(x: bounds.maxX - topRightRadius, y: bounds.minY + topRightRadius), radius: topRightRadius, startAngle: CGFloat(3 * .pi / 2), endAngle: 0, clockwise: true) // 右边缘 path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY - bottomRightRadius)) // 右下圆角 path.addArc(withCenter: CGPoint(x: bounds.maxX - bottomRightRadius, y: bounds.maxY - bottomRightRadius), radius: bottomRightRadius, startAngle: 0, endAngle: CGFloat(.pi / 2), clockwise: true) // 下边缘 path.addLine(to: CGPoint(x: bounds.minX + bottomLeftRadius, y: bounds.maxY)) // 左下圆角 path.addArc(withCenter: CGPoint(x: bounds.minX + bottomLeftRadius, y: bounds.maxY - bottomLeftRadius), radius: bottomLeftRadius, startAngle: CGFloat(.pi / 2), endAngle: CGFloat(.pi), clockwise: true) // 左边缘 path.addLine(to: CGPoint(x: bounds.minX, y: bounds.minY + topLeftRadius)) // 左上圆角 path.addArc(withCenter: CGPoint(x: bounds.minX + topLeftRadius, y: bounds.minY + topLeftRadius), radius: topLeftRadius, startAngle: CGFloat(.pi), endAngle: CGFloat(3 * .pi / 2), clockwise: true) // 闭合路径 path.close() // 2. 设置圆角遮罩 let maskLayer = CAShapeLayer() maskLayer.path = path.cgPath self.layer.mask = maskLayer // 3. 设置阴影,确保阴影路径和圆角路径一致 self.layer.masksToBounds = false self.layer.shadowColor = shadowColor?.cgColor self.layer.shadowOffset = CGSize(width: shadowOffsetWidth, height: shadowOffsetHeight) self.layer.shadowOpacity = shadowOpacity self.layer.shadowPath = path.cgPath } }
关键说明:
- 手动构建路径:通过
addArc方法分别给四个角绘制不同半径的圆弧,再用addLine连接各边,确保路径完全匹配你想要的圆角效果。 - 遮罩与阴影同步:把同一个路径同时作为
layer.mask(实现圆角)和layer.shadowPath(实现和圆角完全贴合的阴影),这样阴影不会出现“漏角”或者形状不符的问题。 - IBInspectable支持:四个角的半径都可以在Storyboard的Attributes Inspector里直接修改,实时预览效果,不用每次改代码。
使用方法:
- 把这段代码添加到你的项目中
- 在Storyboard里把你的View的Class改成
CustomCornerCard - 在Attributes面板里找到对应的四个圆角属性,分别设置你需要的数值(比如左上5、左下10、右上20、右下30)
- 调整阴影属性到你想要的效果
这样就能实现你预期的四个角不同半径的Card View了,阴影也会完美贴合圆角形状。
内容的提问来源于stack exchange,提问作者Nikesh Hyanju
相关产品推荐
相关产品推荐

