ios – 在UIBlurEffect上画一个洞

Xcode 8.0 – Swift 2.3
我有一个内部扩展来创建效果很好的模糊层:
internal extension UIView {

    /**
     Add and display on current view a blur effect.
     */
    internal func addBlurEffect(style style: UIBlurEffectStyle = .ExtraLight,atPosition position: Int = -1) -> UIView {
        // Blur Effect
        let blurEffectView = self.createBlurEffect(style: style)
        if position >= 0 {
            self.insertSubview(blurEffectView,atIndex: position)
        } else {
            self.addSubview(blurEffectView)
        }
        return blurEffectView
    }

    internal func createBlurEffect(style style: UIBlurEffectStyle = .ExtraLight) -> UIView {
        let blurEffect = UIBlurEffect(style: style)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = self.bounds
        blurEffectView.autoresizingMask = [.FlexibleWidth,.FlexibleHeight]
        return blurEffectView
    }

}

问题是:如何在模糊叠加中添加形状孔?
我做了很多尝试:

let p = UIBezierPath(roundedRect: CGRectMake(0.0,0.0,self.viewBlur!.frame.width,self.viewBlur!.frame.height),cornerRadius: 0.0)
p.usesEvenOddFillRule = true
let f = CAShapeLayer()
f.fillColor = UIColor.redColor().CGColor
f.opacity = 0.5
f.fillRule = kCAFillRuleEvenOdd
p.appendPath(self.holePath)
f.path = p.CGPath
self.viewBlur!.layer.addSublayer(f)

但结果是:

我无法理解为什么在UIVisualEffectView上可以使用孔但在_UIVisualEffectBackdropView中没有

UPDATE

我试过@Arun解决方案(使用UIBlurEffectStyle.Dark),但结果不一样:

更新2

有了@ Dim_ov的解决方案,我有:

为了完成这项工作,我需要以这种方式隐藏_UIVisualEffectBackdropView:

for v in effect.subviews {
        if let filterView = NSClassFromString("_UIVisualEffectBackdropView") {
            if v.isKindOfClass(filterView) {
                v.hidden = true
            }
        }
    }

解决方法

在iOS 10中,您必须使用UIVisualEffectView的mask属性而不是CALayer的掩码.

对于iOS 10或Xcode 8的早期版本,我在发行说明中看到了这一点,但我现在找不到这些注释:).我一找到它就会用适当的链接更新我的答案.

所以这是在iOS 10 / Xcode 8中运行的代码:

class ViewController: UIViewController {
    @IBOutlet var blurView: UIVisualEffectView!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        updateBlurViewHole()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        updateBlurViewHole()
    }

    func updateBlurViewHole() {
        let maskView = UIView(frame: blurView.bounds)
        maskView.clipsToBounds = true;
        maskView.backgroundColor = UIColor.clear

        let outerbezierPath = UIBezierPath.init(roundedRect: blurView.bounds,cornerRadius: 0)
        let rect = CGRect(x: 150,y: 150,width: 100,height: 100)
        let innerCirclepath = UIBezierPath.init(roundedRect:rect,cornerRadius:rect.height * 0.5)
        outerbezierPath.append(innerCirclepath)
        outerbezierPath.usesEvenOddFillRule = true

        let fillLayer = CAShapeLayer()
        fillLayer.fillRule = kCAFillRuleEvenOdd
        fillLayer.fillColor = UIColor.green.cgColor // any opaque color would work
        fillLayer.path = outerbezierPath.cgPath
        maskView.layer.addSublayer(fillLayer)

        blurView.mask = maskView;
    }
}

Swift 2.3版本:

class ViewController: UIViewController {
    @IBOutlet var blurView: UIVisualEffectView!

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        updateBlurViewHole()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        updateBlurViewHole()
    }

    func updateBlurViewHole() {
        let maskView = UIView(frame: blurView.bounds)
        maskView.clipsToBounds = true;
        maskView.backgroundColor = UIColor.clearColor()

        let outerbezierPath = UIBezierPath.init(roundedRect: blurView.bounds,cornerRadius:rect.height * 0.5)
        outerbezierPath.appendPath(innerCirclepath)
        outerbezierPath.usesEvenOddFillRule = true

        let fillLayer = CAShapeLayer()
        fillLayer.fillRule = kCAFillRuleEvenOdd
        fillLayer.fillColor = UIColor.greenColor().CGColor
        fillLayer.path = outerbezierPath.CGPath
        maskView.layer.addSublayer(fillLayer)

        blurView.maskView = maskView
    }
}

UPDATE

嗯,这是Apple Developer论坛的讨论,而不是iOS发行说明.但是,我认为Apple的代表有答案,这些信息可能被视为“官方”.

讨论链接:https://forums.developer.apple.com/thread/50854#157782

Masking the layer of a visual effect view is not guaranteed to produce
the correct results – in some cases on iOS 9 it would produce an
effect that looked correct,but potentially sourced the wrong content.
Visual effect view will no longer source the incorrect content,but
the only supported way to mask the view is to either use cornerRadius
directly on the visual effect view’s layer (which should produce the
same result as you are attempting here) or to use the visual effect
view’s maskView property.

以上是来客网为你收集整理的ios – 在UIBlurEffect上画一个洞全部内容,希望文章能够帮你解决ios – 在UIBlurEffect上画一个洞所遇到的程序开发问题。

如果觉得来客网网站内容还不错,欢迎将来客网网站推荐给程序员好友。