Reputation: 4589
I'm trying to make 2 corners of a button round. If I select .TopLeft and .BottomLeft like this:
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
than the code works beautifully.
If I chose .TopRight and . BottomRight like this:
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
than I see no round corners. What is going on here?
I already tried adding maskAdsLayer as a subview and it doesn't work.
Upvotes: 5
Views: 3263
Reputation: 879
After finding this answer (thanks for the kickstart), and experimenting with the missing details, here my final understanding:
We can use the ability to have a custom layer shape class for UIView to encapsulate this a bit. So first, we define our own layer class with a CAShapeLayer mask:
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
}
}
Then we can use it in a 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)
}
}
There is more work to make the corners customizable, but that's the spirit.
Upvotes: 0
Reputation: 437632
If you are doing this in viewDidLoad
, the auto layout constraints may not have been applied by this point, and thus the frame of your button may not be at its final value, and thus disableAdsButton.bounds
is probably not what you expect it to be at that point. Thus, the corners that are being rounded to the right may not be visible. You can confirm this by logging the bounds
of the button at the point this code runs and then look at it again after the views have been laid out.
You can resolve this by deferring this until viewDidAppear
or, better, viewDidLayoutSubviews
.
Upvotes: 5