Andrei Herford
Andrei Herford

Reputation: 18729

Create round UIButton with custom drawRect: method

My goal is to create a custom UIButton subclass, that creates a round (or round rect) button with some additional features.

After some searching, I found that simply setting the cornerRadius of the button layer is the easiest way to make the button round:

@implementation MyRoundButton

-(id)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame])
        [self setupView];

    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    if(self = [super initWithCoder:aDecoder])
        [self setupView];

    return self;
}

-(void)setupView {    
    self.layer.cornerRadius = MIN(self.frame.size.height, self.frame.size.width) / 2.0;
}

This works fine to, as long as I do not override drawRect:

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
}

Of course I would like to add some custom drawing code to drawRect: but even if only [super drawRect:rect] the button is not round anymore: It drawn as rectangle within its bounds.

How is this possible? How can overriding a method with a simple super call change the behavior at all?

How can I avoid this problem? I already tried to let the layer unchanged and to simply draw the background manually in drawRect:. However the button draws its background rect anyway and my custom drawing is on top of it.

So, how to solve this?

Upvotes: 1

Views: 746

Answers (2)

jlehr
jlehr

Reputation: 15597

The layer in your example conceptually contains a background with a corner radius, but the empty override of drawRect: causes that to be ignored. That's because, ordinarily, an instance of UIView depends on its built-in layer (an instance of CALayer) to render its content, so drawRect: isn't called. However, the layer is capable of delegating drawing behavior to its view, and will do so if you implement drawRect:.

If you're simply subclassing UIView, this shouldn't present any problem. However, subclassing a framework component such as UIButton is a bit dicier. One potential issue is the call to -[super drawRect:]; it's hard to know precisely what mischief that might cause, but that may be the source of the problem. By default, a UIButton doesn't need to do any custom drawing; it contains a nested instance of a private class, UIButtonLabel, that draws the button's title.

Instead of trying to override the drawing behavior of a class whose inner details are private, consider using one or more static images and simply setting the button's background image property for one or more states.

Upvotes: 2

DonMag
DonMag

Reputation: 77490

See if this changes anything...

-(void)setupView {    
    self.layer.cornerRadius = MIN(self.frame.size.height, self.frame.size.width) / 2.0;
    self.clipsToBounds = YES;
}

Upvotes: 0

Related Questions