ios – 在UIBlurEffect上画一个洞

前端之家收集整理的这篇文章主要介绍了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.

原文链接:https://www.f2er.com/iOS/334862.html

猜你在找的iOS相关文章