Gloss hole in UIView

This post is advanced topic of “Shadow” and

Hole in UIView

Please read my previous Create hole in UIView

Gloss

Create shadow.
Create color object and create shadow. But hole is clearColor. So we need create color object and shadow, after it create hole.

Sample

GlossHole.h

#import <UIKit/UIKit.h>
@interface GlossHole : NSObject
@property (nonatomic) UIColor *shadowColor;
@property (nonatomic) UIColor *fillColor;
@property (nonatomic) CGFloat shadowWidth;
@property (nonatomic) CGFloat blur;
- (void)drawRect:(CGRect)rect;
@end

This is not UIView, this is helper class to draw gloss hole.

GlossHole.m

#import "GlossHole.h"

@implementation GlossHole

- (id)init {
    self = [super init];
    if (self) {
        // Initialization code
        self.shadowColor = [UIColor whiteColor];
        self.fillColor = [UIColor clearColor];
        self.blur = 5.0;
        self.shadowWidth = 4.0;
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // Draw all direction
    [self drawShadowShape:context rect:rect x:self.shadowWidth y:self.shadowWidth];
    [self drawShadowShape:context rect:rect x:self.shadowWidth y:-self.shadowWidth];
    [self drawShadowShape:context rect:rect x:-self.shadowWidth y:self.shadowWidth];
    [self drawShadowShape:context rect:rect x:-self.shadowWidth y:-self.shadowWidth];
    
    // Draw clear shape
    CGContextSetFillColorWithColor(context, self.fillColor.CGColor);
    CGContextSetBlendMode(context, kCGBlendModeCopy);
    CGContextAddEllipseInRect(context, rect);
    CGContextFillPath(context);
}

- (void)drawShadowShape:(CGContextRef)context rect:(CGRect)rect x:(CGFloat)x y:(CGFloat)y {
    CGContextSetFillColorWithColor(context, self.shadowColor.CGColor);
    CGContextSetShadowWithColor(context, CGSizeMake(x, y), self.blur, [UIColor whiteColor].CGColor);
    CGContextAddEllipseInRect(context, rect);
    CGContextFillPath(context);
}
@end

How to use

HoleView.h

#import <UIKit/UIKit.h>
@interface HoleView : UIView
@property (nonatomic) UIColor *shadowColor;
@end

HoleView.m

@implementation HoleView

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

- (void)drawRect:(CGRect)rect {
    
    GlossHole *hole = [[GlossHole alloc] init];
    [hole drawRect:CGRectMake(100, 50, 100, 100)];
}

Use

ViewController.m

#import "ViewController.h"
#import "HoleView.h"
#import "GlossHole.h"

@interface ViewController ()
@property (nonatomic)UIButton *button;
@property (nonatomic)HoleView *holeView;
@end

@implementation ViewController

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.button = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.button setTitle:@"Touch me!" forState:UIControlStateNormal];
    [self.button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.holeView = [[HoleView alloc] init];
    self.holeView.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.7];
    [self.view addSubview:self.button];
    [self.view addSubview:self.holeView];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)viewWillLayoutSubviews {
    self.button.frame = CGRectMake(100, 100, 100, 40);
    self.holeView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
@end

Result

Gloss Hole