So I will be having a few different rounded buttons within an app (all the way to circular buttons), and from what I can tell, the easiest way to achieve this is to set the cornerRadius property of the buttons CALayer.
However, I don't want to be doing this manually for every button that requires it in every controller, so I thought a simple subclass that sets this on init would be the way.
I am using Storyboard and Autolayout to position and size the buttons, and assigning them to this subclass.
class RoundedButton: UIButton {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.layer.cornerRadius = self.bounds.size.height / 2.0
self.clipsToBounds = true
NSLog("BUTTON BOUNDS: H-%f W-%f", self.bounds.size.height, self.bounds.size.width)
NSLog("BUTTON FRAME: H-%f W-%f", self.frame.height, self.frame.width)
}
}
But I have come to find out that at this point (i.e. init), the size of neither the frame nor bounds are final. For a button in Storyboard sized (and constrained) to H40 x W40, the bounds/frame sizes are showing H30 x W38.
This means that cornerRadius doesn't get the value I expect.
I have confirmed that at some later point (e.g. when the button can already respond to a tap) that its frame/bounds are indeed H40 x W40.
So after all that, my question is, within the UIButton subclass, when/where can I safely set cornerRadius using the final frame/bounds values of the instance?
If you want your code to be executed after the view has gone through AutoLayout you must do it in layoutSubviews
after calling super.layoutSubviews()
.
Like this :
class RoundedButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = bounds.size.height / 2.0
clipsToBounds = true
}
}
This code is not perfect though because it doesn't support when height is bigger than width (easy to fix though…).
Try this in Button class.
override func layoutSubviews() {
super.layoutSubviews()
// here...
}
Since you wish to use initWithCoder rather than initWithFrame (where you do have the frame struct), you can override the layoutSubviews method. When layoutSubviews is called the frame is correct.
In objective-c you can write
- (void)layoutSubviews {
[super layoutSubviews];
self.layer.cornerRadius = self.bounds.size.height/2;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With