I am trying to override the drawRect:
method of UIView in my custom view. However, my view has a border radius defined as:
sub = [[[NSBundle mainBundle] loadNibNamed:@"ProfileView" owner:self options:nil] objectAtIndex:0];
[self addSubview:sub];
[sub setUserInteractionEnabled:YES];
[self setUserInteractionEnabled:YES];
CALayer *layer = sub.layer;
layer.masksToBounds = YES;
layer.borderWidth = 5.0;
layer.borderColor = [UIColor whiteColor].CGColor;
layer.cornerRadius = 30.0;
This works perfectly and places a nice border with a border radius around my view (don't mind the diagonal/straight white lines at the back, they have nothing to do with this view):
However, when I try to override the drawRect:
method in my view, I can see a black background not masking to bounds. I don't do anything (currently), here is my code:
-(void)drawRect:(CGRect)rect{
[super drawRect:rect];
}
And here is the result:
I've changed nothing but the draw method. How can I override the draw method while keeping my view obey the corner radius mask? Is this a bug in iOS or am I missing something?
I don't know the full answer, but I do know that UIView's implementation of drawLayer:inContext:
works differently depending on whether you have implemented drawRect:
or not. Perhaps masking/clipping to bounds is one of those things it does differently.
You can try solving your issue a number of ways:
make your background transparent:
layer.backgroundColor = [UIColor clearColor].CGColor;
clip yourself inside your custom drawRect:
:
- (void)drawRect:(CGRect)rect {
[[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:30.0] addClip];
[image drawInRect:rect]; // or whatever
}
carve out the corners explicitly:
CGContextBeginPath(c);
CGContextAddArc(c, r, r, r, M_PI, 3*M_PI_2, 0);
CGContextAddLineToPoint(c, 0, 0);
CGContextClosePath(c);
CGContextClip(c);
[[UIColor grayColor] setFill];
UIRectFill(rect);
I stole those last 2 suggestions from this great presentation from WWDC 2010: Advanced Performance Optimization on iPhone OS (video listed at this index page -- annoyingly, no direct link).
This is an old question, but I was recently reading a useful blog post titled Abusing UIView. In it the author advises against overriding drawRect
to do things like add a border when there are other ways of doing it. He says,
Overriding
drawRect:
causes a performance hit. I haven’t profiled it, so I don’t know if it’s a signifigant performance under normal circumstances (it’s probably not), but in most cases, folks who overridedrawRect:
can accomplish what they want much easier by setting properties on a view’s layer property. If you need to draw an outline around a view, here’s how you would do it:#import <QuartzCore/QuartzCore.h> - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.layer.borderWidth = 2.f; self.layer.borderColor = [UIColor redColor].CGColor; } return self;
I realize this probably doesn't solve the problem of the black background showing through. It is just something else to think about.
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