-
-
Save aldo-jlaurenstin/2ed6569b1a3746645143 to your computer and use it in GitHub Desktop.
// | |
// MakeTransparentHoleOnOverlayView.swift | |
// | |
// Created by James Laurenstin on 2015-04-10. | |
// Copyright (c) 2015 Aldo Group Inc. All rights reserved. | |
// | |
import UIKit | |
class MakeTransparentHoleOnOverlayView: UIView { | |
@IBOutlet weak var transparentHoleView: UIView! | |
// MARK: - Drawing | |
override func drawRect(rect: CGRect) { | |
super.drawRect(rect) | |
if self.transparentHoleView != nil { | |
// Ensures to use the current background color to set the filling color | |
self.backgroundColor?.setFill() | |
UIRectFill(rect) | |
let layer = CAShapeLayer() | |
let path = CGPathCreateMutable() | |
// Make hole in view's overlay | |
// NOTE: Here, instead of using the transparentHoleView UIView we could use a specific CFRect location instead... | |
CGPathAddRect(path, nil, self.transparentHoleView.frame) | |
CGPathAddRect(path, nil, bounds) | |
layer.path = path | |
layer.fillRule = kCAFillRuleEvenOdd | |
self.layer.mask = layer | |
} | |
} | |
override func layoutSubviews () { | |
super.layoutSubviews() | |
} | |
// MARK: - Initialization | |
required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
} | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
} | |
} |
Thanks!
Swift 3 changes:
class MakeTransparentHoleOnOverlayView: UIView {
@IBOutlet weak var transparentHoleView: UIView!
// MARK: - Drawing
override func draw(_ rect: CGRect) {
super.draw(rect)
if self.transparentHoleView != nil {
// Ensures to use the current background color to set the filling color
self.backgroundColor?.setFill()
UIRectFill(rect)
let layer = CAShapeLayer()
let path = CGMutablePath()
// Make hole in view's overlay
// NOTE: Here, instead of using the transparentHoleView UIView we could use a specific CFRect location instead...
path.addRect(transparentHoleView.frame)
path.addRect(bounds)
layer.path = path
layer.fillRule = kCAFillRuleEvenOdd
self.layer.mask = layer
}
}
override func layoutSubviews () {
super.layoutSubviews()
}
// MARK: - Initialization
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
}
what can I do if I want a circle hole?
@richard182 Probably use path.addEllipse(in: <#T##CGRect#>)
i am new in IOS . How to Use it Any idea ?
Thanks!
This is first time GitHub helped me more then stack overflow
Compiles fine with Xcode9.2 + Swift4. Tested on iOS9 simulator and iOS11 device.
Thank you for this super useful view.
Hey! Thanks for this very useful view!
I have a question though, how can I add some corner radius to the hole view?
Thanks.
There's a simpler way:
Usage:
myOverlayView.makeClearHole(rect: CGRect(x: 100, y: 100, width: 200, height: 200))
Extension:
extension UIView {
func makeClearHole(rect: CGRect) {
let maskLayer = CAShapeLayer()
maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
maskLayer.fillColor = UIColor.black.cgColor
let pathToOverlay = UIBezierPath(rect: self.bounds)
pathToOverlay.append(UIBezierPath(rect: rect))
pathToOverlay.usesEvenOddFillRule = true
maskLayer.path = pathToOverlay.cgPath
layer.mask = maskLayer
}
}
@CodeKunal Just call this method on your UIView
, changing roundedRect
and roundedRectPath
arguments as needed:
extension UIView {
func makeRoundedRectangularHole() {
let entireViewPath = UIBezierPath(rect: self.bounds)
let roundedRect = CGRect(x: 8, y: 8, width: bounds.width - 16, height: bounds.height - 16)
let roundedRectPath = UIBezierPath(roundedRect: roundedRect, byRoundingCorners:.allCorners, cornerRadii: CGSize(width: 16.0, height: 16.0))
entireViewPath.append(roundedRectPath)
entireViewPath.usesEvenOddFillRule = true
let maskLayer = CAShapeLayer()
maskLayer.path = entireViewPath.cgPath
maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
maskLayer.fillColor = UIColor.black.cgColor
layer.mask = maskLayer
}
}
Thanks @vietstone-ng for the original code.
Thanks! This helped me solve a problem in my project.
This custom view allows to create a transparent hole using a child view's frame CGRect location.
I hope this helps someone. It's took me a while to figure this out properly.