UIBezierPath: roundedRect: byRoundingCorners: cornerRadii: 行为很奇怪
UIBezierPath: roundedRect: byRoundingCorners: cornerRadii: acts weird
我正在尝试使按钮的两个角变圆。如果我 select .TopLeft 和 .BottomLeft 是这样的:
let bezierDisableAdsPath = UIBezierPath(roundedRect: disableAdsButton.bounds, byRoundingCorners: [UIRectCorner.TopLeft , UIRectCorner.BottomLeft] , cornerRadii: CGSizeMake(4.0, 4.0))
let maskAdsLayer = CAShapeLayer()
maskAdsLayer.frame = disableAdsButton.bounds
maskAdsLayer.path = bezierDisableAdsPath.CGPath
disableAdsButton.layer.mask = maskAdsLayer
比代码更漂亮。
如果我选择 .TopRight 和 .右下角像这样:
let bezierDisableAdsPath = UIBezierPath(roundedRect: disableAdsButton.bounds, byRoundingCorners: [UIRectCorner.TopRight , UIRectCorner.BottomRight] , cornerRadii: CGSizeMake(4.0, 4.0))
let maskAdsLayer = CAShapeLayer()
maskAdsLayer.frame = disableAdsButton.bounds
maskAdsLayer.path = bezierDisableAdsPath.CGPath
disableAdsButton.layer.mask = maskAdsLayer
比我看到的没有圆角。这是怎么回事?
我已经尝试将 maskAdsLayer 添加为子视图,但它不起作用。
如果您在 viewDidLoad
中执行此操作,此时可能尚未应用自动布局约束,因此您的按钮框架可能未处于最终值,因此 disableAdsButton.bounds
可能不是您当时期望的那样。因此,向右圆化的角可能不可见。您可以通过在此代码运行时记录按钮的 bounds
来确认这一点,然后在布局视图后再次查看它。
您可以通过推迟到 viewDidAppear
或更好的 viewDidLayoutSubviews
.
来解决此问题
找到这个答案(感谢 kickstart),并尝试了缺失的细节,这是我的最终理解:
- 图层只需要创建一次
- 它必须在视图的矩形改变时更新
- 在 layoutSubviews() 中捕获的最佳位置
我们可以使用为 UIView 提供自定义图层形状 class 的功能来稍微封装一下。所以首先,我们用 CAShapeLayer 掩码定义我们自己的层 class:
class RoundedShapeLayer: CAShapeLayer {
override init() {
super.init()
self.mask = CAShapeLayer()
}
override init(layer: Any) {
super.init(layer: layer)
self.mask = CAShapeLayer()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.mask = CAShapeLayer()
}
func update(for bounds: CGRect) {
(mask as! CAShapeLayer).path =
UIBezierPath(roundedRect: bounds,
byRoundingCorners: [UIRectCorner.topRight, UIRectCorner.topLeft],
cornerRadii: CGSize(width: 10, height: 10)).cgPath
}
}
然后我们可以在 UIView 中使用它:
@IBDesignable class RoundedCornerView: UIView {
override class var layerClass: AnyClass {
get {
return RoundedShapeLayer.self
}
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func layoutSubviews() {
super.layoutSubviews()
(layer as! RoundedShapeLayer).update(for: bounds)
}
}
要使边角可自定义还有很多工作要做,但这就是精神。
我正在尝试使按钮的两个角变圆。如果我 select .TopLeft 和 .BottomLeft 是这样的:
let bezierDisableAdsPath = UIBezierPath(roundedRect: disableAdsButton.bounds, byRoundingCorners: [UIRectCorner.TopLeft , UIRectCorner.BottomLeft] , cornerRadii: CGSizeMake(4.0, 4.0))
let maskAdsLayer = CAShapeLayer()
maskAdsLayer.frame = disableAdsButton.bounds
maskAdsLayer.path = bezierDisableAdsPath.CGPath
disableAdsButton.layer.mask = maskAdsLayer
比代码更漂亮。
如果我选择 .TopRight 和 .右下角像这样:
let bezierDisableAdsPath = UIBezierPath(roundedRect: disableAdsButton.bounds, byRoundingCorners: [UIRectCorner.TopRight , UIRectCorner.BottomRight] , cornerRadii: CGSizeMake(4.0, 4.0))
let maskAdsLayer = CAShapeLayer()
maskAdsLayer.frame = disableAdsButton.bounds
maskAdsLayer.path = bezierDisableAdsPath.CGPath
disableAdsButton.layer.mask = maskAdsLayer
比我看到的没有圆角。这是怎么回事?
我已经尝试将 maskAdsLayer 添加为子视图,但它不起作用。
如果您在 viewDidLoad
中执行此操作,此时可能尚未应用自动布局约束,因此您的按钮框架可能未处于最终值,因此 disableAdsButton.bounds
可能不是您当时期望的那样。因此,向右圆化的角可能不可见。您可以通过在此代码运行时记录按钮的 bounds
来确认这一点,然后在布局视图后再次查看它。
您可以通过推迟到 viewDidAppear
或更好的 viewDidLayoutSubviews
.
找到这个答案(感谢 kickstart),并尝试了缺失的细节,这是我的最终理解:
- 图层只需要创建一次
- 它必须在视图的矩形改变时更新
- 在 layoutSubviews() 中捕获的最佳位置
我们可以使用为 UIView 提供自定义图层形状 class 的功能来稍微封装一下。所以首先,我们用 CAShapeLayer 掩码定义我们自己的层 class:
class RoundedShapeLayer: CAShapeLayer {
override init() {
super.init()
self.mask = CAShapeLayer()
}
override init(layer: Any) {
super.init(layer: layer)
self.mask = CAShapeLayer()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.mask = CAShapeLayer()
}
func update(for bounds: CGRect) {
(mask as! CAShapeLayer).path =
UIBezierPath(roundedRect: bounds,
byRoundingCorners: [UIRectCorner.topRight, UIRectCorner.topLeft],
cornerRadii: CGSize(width: 10, height: 10)).cgPath
}
}
然后我们可以在 UIView 中使用它:
@IBDesignable class RoundedCornerView: UIView {
override class var layerClass: AnyClass {
get {
return RoundedShapeLayer.self
}
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func layoutSubviews() {
super.layoutSubviews()
(layer as! RoundedShapeLayer).update(for: bounds)
}
}
要使边角可自定义还有很多工作要做,但这就是精神。