首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在UIBlurEffect上画孔

在UIBlurEffect上画孔
EN

Stack Overflow用户
提问于 2016-10-26 08:09:42
回答 3查看 3.8K关注 0票数 9

Xcode 8.0 -SWIFT2.3

我有一个内部扩展来创建工作非常好的模糊层:

代码语言:javascript
复制
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
    }
    
}

问题是:我如何在模糊的覆盖层中添加一个形状的洞?我已经做了很多尝试:

代码语言:javascript
复制
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里不行

更新

我尝试过@Arun解决方案(使用UIBlurEffectStyle.Dark),但结果并不相同:

更新2

关于@Dim_ov的解决方案,我有:

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

代码语言:javascript
复制
    for v in effect.subviews {
        if let filterView = NSClassFromString("_UIVisualEffectBackdropView") {
            if v.isKindOfClass(filterView) {
                v.hidden = true
            }
        }
    }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-11-03 12:44:46

在iOS 10中,您必须使用UIVisualEffectViewmask属性,而不是CALayermask

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

下面是在iOS 10/Xcode 8中工作的代码:

代码语言:javascript
复制
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版本:

代码语言:javascript
复制
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: 0)
        let rect = CGRect(x: 150, y: 150, width: 100, height: 100)
        let innerCirclepath = UIBezierPath.init(roundedRect:rect, 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
    }
}

更新

好吧,这是苹果开发者论坛的讨论,而不是iOS发布说明。但是苹果公司的代表也给出了答案,所以我认为,这些信息可能被认为是“官方的”。

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

掩盖视觉效果视图的图层并不一定会产生正确的结果--在某些情况下,在iOS 9上,它会产生一个看起来正确的效果,但可能会产生错误的内容。视觉效果视图将不再来源于不正确的内容,但是唯一支持的掩盖视图的方法是直接在视觉效果视图的层上使用cornerRadius (这应该会产生与您在这里尝试的结果相同的结果),或者使用视觉效果视图的maskView属性。

票数 19
EN

Stack Overflow用户

发布于 2016-11-03 09:38:31

请在这里检查我的代码

内扩展UIView {

代码语言:javascript
复制
/**
 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
}

}

类ViewController: UIViewController {

代码语言:javascript
复制
@IBOutlet weak var blurView: UIImageView!

var blurEffectView: UIView!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    blurEffectView = blurView.addBlurEffect(style: UIBlurEffectStyle.Light, atPosition: 0)


}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let outerbezierPath = UIBezierPath.init(roundedRect: self.blurEffectView.frame, cornerRadius: 0)
    let rect = CGRectMake(150, 150, 100, 100)
    let innerCirclepath = UIBezierPath.init(roundedRect:rect, cornerRadius:rect.height * 0.5)
    outerbezierPath.appendPath(innerCirclepath)
    outerbezierPath.usesEvenOddFillRule = false
    let fillLayer = CAShapeLayer()
    fillLayer.fillRule = kCAFillRuleEvenOdd
    fillLayer.fillColor = UIColor.blackColor().CGColor
    fillLayer.path = outerbezierPath.CGPath
    self.blurEffectView.layer.mask = fillLayer
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}与UIBlurEffectStyle.Light

用UIBlurEffectStyle.Dark

用UIBlurEffectStyle.ExtraLight

票数 3
EN

Stack Overflow用户

发布于 2017-04-11 14:22:50

我的代码中也有同样的问题。当我在包含UIViewUIVisualEffectView上涂上面具后,模糊消失了。但是,我可以通过重写父服务器上的draw方法来返回它:

代码语言:javascript
复制
override func draw(_ rect: CGRect) {
    super.draw(rect)
}

我不知道它为什么会起作用,但希望它能帮助到别人。我用来挖洞的代码是:

代码语言:javascript
复制
private func makeViewFinderMask() -> CAShapeLayer {

    let path = UIBezierPath(rect: bounds)
    let croppedPath = UIBezierPath(roundedRect: viewFinderBounds(), cornerRadius: viewFinderRadius)
    path.append(croppedPath)
    path.usesEvenOddFillRule = true

    let mask = CAShapeLayer()
    mask.path = path.cgPath
    mask.fillRule = kCAFillRuleEvenOdd
    return mask
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40256942

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档