Search code examples
cocoacocoa-touchrounded-cornersquartz-2dcgcontext

How can I remove a UIView with rounded corners from its parent view?


I'm creating an iPad app for 3.2 and later. My app has an overlay view which has a semi-transparency that makes everything below it darker. In the middle of this view I am chopping a hole in this semi-transparency to let part of the background filter through unscathed, with this code:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGRect intersection = CGRectIntersection(hole.frame, rect);
    CGContextClearRect(context, intersection);
}

Additionally, the 'hole' view has rounded corners, applied via:

self.layer.cornerRadius = 4.25;

This works great except for one small problem - these rounded corners are not taken into account, so the hole that gets chopped out has square corners instead of rounded. I need to fix this, but I have no idea how. Any ideas, examples, thoughts?


Solution

  • Here's how I ended up getting it to work. This produces a hole with the same frame as the 'hole' UIView, cutting it out from self (UIView). This lets you see whatever is behind the 'hole' unhindered.

    - (void)drawRect:(CGRect)rect {
        CGFloat radius = self.hole.layer.cornerRadius;
        CGRect c = self.hole.frame;
        CGContextRef context = UIGraphicsGetCurrentContext();
    
            // this simply draws a path the same shape as the 'hole' view
        CGContextMoveToPoint(context, c.origin.x, c.origin.y + radius);
        CGContextAddLineToPoint(context, c.origin.x, c.origin.y + c.size.height - radius);
        CGContextAddArc(context, c.origin.x + radius, c.origin.y + c.size.height - radius, radius, M_PI_4, M_PI_2, 1);
        CGContextAddLineToPoint(context, c.origin.x + c.size.width - radius, c.origin.y + c.size.height);
        CGContextAddArc(context, c.origin.x + c.size.width - radius, c.origin.y + c.size.height - radius, radius, M_PI_2, 0.0f, 1);
        CGContextAddLineToPoint(context, c.origin.x + c.size.width, c.origin.y + radius);
        CGContextAddArc(context, c.origin.x + c.size.width - radius, c.origin.y + radius, radius, 0.0f, -M_PI_2, 1);
        CGContextAddLineToPoint(context, c.origin.x + radius, c.origin.y);
        CGContextAddArc(context, c.origin.x + radius, c.origin.y + radius, radius, -M_PI_2, M_PI, 1);
    
            // finish
        CGContextClosePath(context);
        CGContextClip(context); // this is the secret sauce
        CGContextClearRect(context, c);
    }