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
我试过@Arun解决方案(使用UIBlurEffectStyle.Dark),但结果不一样:
为了完成这项工作,我需要以这种方式隐藏_UIVisualEffectBackdropView
:
for v in effect.subviews {
if let filterView = NSClassFromString("_UIVisualEffectBackdropView") {
if v.isKindOfClass(filterView) {
v.hidden = true
}
}
}
答案 0 :(得分:10)
在iOS 10中,您必须使用mask
的{{1}}属性,而不是UIVisualEffectView
的{{1}}。
我在iOS 10或Xcode 8的早期测试版的发行说明中看到了这一点,但我现在找不到这些注释:)。我会在找到后立即用适当的链接更新我的答案。
所以这是适用于iOS 10 / Xcode 8的代码:
CALayer
Swift 2.3版本:
mask
<强>更新强>
嗯,这是Apple Developer论坛的讨论,而不是iOS发行说明。但是Apple的代表也有答案,所以我认为,这些信息可能被视为“官方”。
讨论的链接:https://forums.developer.apple.com/thread/50854#157782
无法保证屏蔽视觉效果视图的图层 正确的结果 - 在iOS 9的某些情况下,它会产生一个 效果看起来不错,但可能来源错误。 视觉效果视图将不再提供不正确的内容,但是 屏蔽视图的唯一方法是使用cornerRadius 直接在视觉效果视图的层(应该产生的 你在这里尝试的结果相同)或使用视觉效果 view的maskView属性。
答案 1 :(得分:3)
请在此处查看我的代码
内部扩展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.
}
答案 2 :(得分:0)
我的代码中遇到了同样的问题。我在包含UIView
的{{1}}上应用了蒙版后,模糊消失了。但是,我可以通过覆盖父级的UIVisualEffectView
方法将其转回:
draw
我不知道为什么它能正常工作,但希望它会帮助某人。我用来削减漏洞的代码:
override func draw(_ rect: CGRect) {
super.draw(rect)
}