概述
如題舶替,實現(xiàn)上述需求
思路
- 添加 contentView符隙,contentView 首先添加一個 shapeLayer
- 繼續(xù)向 contentView 添加一個 Label,
Label.backgroundColor = .clear
- 在 contentView layoutSubviews() 中配置 shapeLayer崇棠,并且 shapeLayer 傳入的是 Label.bounds
override func layoutSubviews() {
super.layoutSubviews()
configShadowLayer()
}
其中, configShadowLayer() 主要是通過 UIBezierPath 繪制 Label 的形狀,并添加陰影
struct CornerRadii {
let topLeft: CGFloat
let topRight: CGFloat
let bottomLeft: CGFloat
let bottomRight: CGFloat
init(topLeft: CGFloat, topRight: CGFloat, bottomLeft: CGFloat, bottomRight: CGFloat) {
self.topLeft = topLeft
self.topRight = topRight
self.bottomLeft = bottomLeft
self.bottomRight = bottomRight
}
}
private func CYPathCreateWIthRoundedRect(bounds: CGRect, cornerRadii: CornerRadii) -> UIBezierPath {
let minX = bounds.minX
let minY = bounds.minY
let maxX = bounds.maxX
let maxY = bounds.maxY
let topLeftCenterX = minX + cornerRadii.topLeft
let topLeftCenterY = minY + cornerRadii.topLeft
let topRightCenterX = maxX - cornerRadii.topRight
let topRightCenterY = minY + cornerRadii.topRight
let bottomLeftCenterX = minX + cornerRadii.bottomLeft
let bottomLeftCenterY = maxY - cornerRadii.bottomLeft
let bottomRightCenterX = maxX - cornerRadii.bottomRight
let bottomRightCenterY = maxY - cornerRadii.bottomRight
let path = UIBezierPath.init()
path.move(to: CGPoint(x: topLeftCenterX, y: minY))
// 頂左
path.addArc(withCenter: CGPoint(x: topLeftCenterX, y: topLeftCenterY), radius: cornerRadii.topLeft, startAngle: CGFloat.pi / 2 * 3, endAngle: CGFloat.pi, clockwise: false)
path.addLine(to: CGPoint(x: minX, y: bottomLeftCenterY))
// 底左
path.addArc(withCenter: CGPoint(x: bottomLeftCenterX, y: bottomLeftCenterY), radius: cornerRadii.bottomLeft, startAngle: CGFloat.pi, endAngle: CGFloat.pi / 2, clockwise: false)
// 畫三角形
path.addLine(to: CGPoint(x: bottomLeftCenterX + 21, y: maxY))
path.addLine(to: CGPoint(x: bottomLeftCenterX + 21 + 7, y: maxY + 6.2))
path.addLine(to: CGPoint(x: bottomLeftCenterX + 21 + 14, y: maxY))
path.addLine(to: CGPoint(x: bottomRightCenterX, y: maxY))
// 底右
path.addArc(withCenter: CGPoint(x: bottomRightCenterX, y: bottomRightCenterY), radius: cornerRadii.bottomRight, startAngle: CGFloat.pi / 2, endAngle: 0, clockwise: false)
path.addLine(to: CGPoint(x: maxX, y: topRightCenterY))
// 頂右
path.addArc(withCenter: CGPoint(x: topRightCenterX, y: topRightCenterY), radius: cornerRadii.topRight, startAngle: 0, endAngle: CGFloat.pi / 2 * 3, clockwise: false)
path.close()
return path
}
func configShadowLayer() {
let cornerRadii = CornerRadii(topLeft: 20, topRight: 20, bottomLeft: 20, bottomRight: 20)
let path = CYPathCreateWIthRoundedRect(bounds: tipsLabel.bounds, cornerRadii: cornerRadii)
shadowLayer.fillColor = UIColor.white.cgColor
shadowLayer.path = path.cgPath
shadowLayer.shadowPath = path.cgPath
shadowLayer.shadowOpacity = 1
shadowLayer.shadowColor = UIColor.gray.cgColor
shadowLayer.shadowRadius = 6
shadowLayer.shadowOffset = CGSize(width: 0, height: 2)
}
注意:path.addArc(withCenter: CGPoint(x: topLeftCenterX, y: topLeftCenterY), radius: cornerRadii.topLeft, startAngle: CGFloat.pi / 2 * 3, endAngle: CGFloat.pi, clockwise: false)
中 圓角的startAngle 與 endAngle 均為順時針角度坝辫,具體如圖
拓展
1. 有圓角的UIView 添加陰影
思路:
view.backgroundColor = .clear
- 按照上文思路,設置 CAShapeLayer射亏,作為 shadowLayer近忙,然后
layer.addSublayer(shadowLayer)
,如果所有的圓角半徑都一樣的話智润,可以使用如下方法更簡單一些let berPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topRight , .topLeft, .bottomLeft, .bottomRight], cornerRadii: CGSize(width: 8, height: 8))
- 添加一個 containerView, 其它所有的控件添加到這個 containerView 上及舍,同時設置
containerView.layer.maskToBounds = true
, 以及 borderColor窟绷、borderWidth 等 - 如果使用 SnapKit, 需要
override func layoutSubviews()
锯玛,在layoutSubviews()
方法中調用 生成 shadowLayer 的方法,或者在確定當前 view 尺寸以后再調用也可以兼蜈。
2. 繪制分別有不同的圓角的 UIView
也可以通過上述方法繪制 UIView 四個角分別有不同的圓角攘残,原理與設置圓角的幾種方式類似