Xcode 8.0 -SWIFT2.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里不行
更新
我尝试过@Arun解决方案(使用UIBlurEffectStyle.Dark),但结果并不相同:

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

为了完成这项工作,我需要以这样的方式隐藏_UIVisualEffectBackdropView:
for v in effect.subviews {
if let filterView = NSClassFromString("_UIVisualEffectBackdropView") {
if v.isKindOfClass(filterView) {
v.hidden = true
}
}
}发布于 2016-11-03 12:44:46
在iOS 10中,您必须使用UIVisualEffectView的mask属性,而不是CALayer的mask。
我在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: 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属性。

发布于 2016-11-03 09:38:31
请在这里检查我的代码
内扩展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
}}
类ViewController: UIViewController {
@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

发布于 2017-04-11 14:22:50
我的代码中也有同样的问题。当我在包含UIView的UIVisualEffectView上涂上面具后,模糊消失了。但是,我可以通过重写父服务器上的draw方法来返回它:
override func draw(_ rect: CGRect) {
super.draw(rect)
}我不知道它为什么会起作用,但希望它能帮助到别人。我用来挖洞的代码是:
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
}https://stackoverflow.com/questions/40256942
复制相似问题