Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best place to set cornerRadius based on UIButton size in subclass?

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?

like image 484
RobertoCuba Avatar asked Jul 27 '15 13:07

RobertoCuba


3 Answers

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…).

like image 168
Fantattitude Avatar answered Nov 03 '22 00:11

Fantattitude


Try this in Button class.

override func layoutSubviews() {
    super.layoutSubviews()

    // here...
}
like image 21
tom.e.kid Avatar answered Nov 03 '22 00:11

tom.e.kid


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;

}
like image 1
Orn Arnarson Avatar answered Nov 03 '22 00:11

Orn Arnarson