Mask a UIView with a cut-out circle Mask a UIView with a cut-out circle ios ios

Mask a UIView with a cut-out circle


So, here’s what I did. I created a custom UIView subclass called BlackoutView, like so:

BlackoutView.h

#import <UIKit/UIKit.h>@interface BlackoutView : UIView@property (nonatomic, retain) UIColor *fillColor;@property (nonatomic, retain) NSArray *framesToCutOut;@end

BlackoutView.m

#import "BlackoutView.h"@implementation BlackoutView- (void)drawRect:(CGRect)rect{    [self.fillColor setFill];    UIRectFill(rect);    CGContextRef context = UIGraphicsGetCurrentContext();    CGContextSetBlendMode(context, kCGBlendModeDestinationOut);    for (NSValue *value in self.framesToCutOut) {        CGRect pathRect = [value CGRectValue];        UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:pathRect];        [path fill];    }    CGContextSetBlendMode(context, kCGBlendModeNormal);}@end

I then instantiate it as normal, and set the properties to the colour of the mask I want to use, and the frames to be cut out of the mask:

[blackMask setFillColor:[UIColor colorWithWhite:0.0f alpha:0.8f]];[blackMask setFramesToCutOut:@[[NSValue valueWithCGRect:buttonCircleA.frame],                               [NSValue valueWithCGRect:buttonCircleB.frame]]];

This could be improved by allowing me to cut out other shapes besides ovals, but it’s fine for my purposes here and would be easily adapted to do so later. Hopefully this helps others!


If You are using any Black Image to mask then

-(void)maskWithImage:(UIImage*)maskImage toImageView:(UIImageView*)imgView{    CALayer *aMaskLayer=[CALayer layer];    aMaskLayer.contents=(id)maskImage.CGImage;    imgView.layer.mask=aMaskLayer;}

If you have any Custom ShapeLayer to mask

-(void)maskWithShapeLayer:(CALayer*)layer toImageView:(UIImageView*)imgView{    //Layer should be filled with Black color to mask those part of Image    imgView.layer.mask=layer;}

If You want to make ImageView Mask with Circle

-(void)maskWithCircle:(UIImageView*)imgView{    CAShapeLayer *aCircle=[CAShapeLayer layer];    aCircle.path=[UIBezierPath bezierPathWithRoundedRect:imgView.bounds cornerRadius:imgView.frame.size.height/2].CGPath; // Considering the ImageView is square in Shape    aCircle.fillColor=[UIColor blackColor].CGColor;    imgView.layer.mask=aCircle;}


Here is my conversion of the accepted answer in Swift:

public class OverlayView: UIView {let fillColor: UIColor = UIColor.grayColor()public var framesToCutOut: Array<NSValue> = [NSValue]()override public func drawRect(rect: CGRect) {    super.drawRect(rect)    fillColor.setFill()    UIRectFill(rect)    if let context: CGContextRef = UIGraphicsGetCurrentContext() {        CGContextSetBlendMode(context, .DestinationOut)        for value in framesToCutOut {            let pathRect: CGRect = value.CGRectValue()            let path: UIBezierPath = UIBezierPath(ovalInRect: pathRect)            path.fill()        }        CGContextSetBlendMode(context, .Normal)    }}