I have a simple UIViewController with UIVisualEffectView presented over another controller using overCurrentContext
.
and it is fine.
now I try to make a hole inside that view the following way:
class CoverView: UIView {
private let blurView: UIVisualEffectView = {
UIVisualEffectView(effect: UIBlurEffect(style: .dark))
}()
// MARK: - Internal
func setup() {
addSubview(blurView)
blurView.snp.makeConstraints { maker in
maker.edges.equalToSuperview()
}
blurView.makeClearHole(rect: CGRect(x: 100, y: 100, width: 100, height: 230))
}
}
extension UIView {
func makeClearHole(rect: CGRect) {
let maskLayer = CAShapeLayer()
maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
maskLayer.fillColor = UIColor.black.cgColor
let pathToOverlay = UIBezierPath(rect: bounds)
pathToOverlay.append(UIBezierPath(rect: rect))
pathToOverlay.usesEvenOddFillRule = true
maskLayer.path = pathToOverlay.cgPath
layer.mask = maskLayer
}
}
But the effect is reversed than I expected, why?
I need everything around blurred the way how rectangle currently is. And the rect inside should be transparent.
EDIT::
I have studied everything from comments below, and tried another answer, but result is still the same. Why?;) I have no idea what is wrong.
private func makeClearHole(rect: CGRect) {
let maskLayer = CAShapeLayer()
maskLayer.fillColor = UIColor.black.cgColor
let pathToOverlay = CGMutablePath()
pathToOverlay.addRect(blurView.bounds)
pathToOverlay.addRect(rect)
maskLayer.path = pathToOverlay
maskLayer.fillRule = .evenOdd
blurView.layer.mask = maskLayer
}
CodePudding user response:
Well I tested your code and the original code with makeClearHole function in the extension works fine! The problem lies somewhere else.
1- Change the CoverView as following*
class CoverView: UIView {
private lazy var blurView: UIVisualEffectView = {
let bv = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
bv.frame = bounds
return bv
}()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Internal
func setup() {
addSubview(blurView)
blurView.snp.makeConstraints { maker in
maker.edges.equalToSuperview()
}
blurView.makeClearHole(rect: CGRect(x: 100, y: 100, width: 100, height: 230))
}
}
2- Give a frame to coverView in your view controller The view controller you have is different. But you should give the CoverView instance a frame. This is how: (again, this is how I tested but your view controller is definitely different)
class ViewController: UIViewController {
var label: UILabel!
var coverView: CoverView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
label = UILabel()
label.text = "HELLO WORLD"
label.font = UIFont.systemFont(ofSize: 40, weight: .black)
coverView = CoverView(frame: CGRect(x: 20, y: 200, width: 300, height: 400))
view.addSubview(label)
view.addSubview(coverView)
label.snp.makeConstraints { make in
make.center.equalTo(view)
}
coverView.snp.makeConstraints { make in
make.width.equalTo(coverView.bounds.width)
make.height.equalTo(coverView.bounds.height)
make.leading.equalTo(view).offset(coverView.frame.minX)
make.top.equalTo(view).offset(coverView.frame.minY)
}
}
}
** Result**