iOS 10 上的 UIVisualEffectView 蒙版

Posted

技术标签:

【中文标题】iOS 10 上的 UIVisualEffectView 蒙版【英文标题】:UIVisualEffectView mask on iOS 10 【发布时间】:2016-10-23 09:12:24 【问题描述】:

我有一个 UIVisualEffectView 和一个我想要查看的形状 (CGPath)。

我听说屏蔽 UIVisualEffectView 可以做到这一点。

所以我所做的(PocketSVG 是一个 API,可以帮助您将 SVG 文件转换为 CGPath)。代码:

let blur: UIBlurEffect = UIBlurEffect(style: .Light)
let ev: UIVisualEffectView = UIVisualEffectView(effect: blur)
ev.frame = self.frame
ev.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(ev)

ev.rightAnchor.constraintEqualToAnchor(self.rightAnchor).active = true
ev.bottomAnchor.constraintEqualToAnchor(self.bottomAnchor).active = true
ev.leftAnchor.constraintEqualToAnchor(self.leftAnchor).active = true
ev.heightAnchor.constraintEqualToAnchor(self.heightAnchor, multiplier: 1.5).active = true

let myPath: CGPathRef = PocketSVG.pathFromSVGFileNamed("CategoriesBar").takeUnretainedValue()
var transform: CGAffineTransform = CGAffineTransformMakeScale(self.frame.size.width / 754.0, self.frame.size.height / 220.0)

let transformedPath: CGPathRef = CGPathCreateMutableCopyByTransformingPath(myPath, &transform)!

let maskLayer = CAShapeLayer()
maskLayer.path = transformedPath
maskLayer.fillRule = kCAFillRuleEvenOdd

let maskView = UIView(frame: self.frame)
maskView.backgroundColor = UIColor.blackColor()
maskView.layer.mask = maskLayer

ev.maskView = maskView

它在ios 9 及以下版本上运行良好,但在iOS 10Xcode 8 上不起作用(没有模糊,只有透明视图)。

如果有人想尝试,这是我的SVG 文件的链接:

https://www.dropbox.com/s/mjql2bzf37vpl2r/CategoriesBar.svg?dl=0

知道如何让它在iOS 10 上也能正常工作吗?

谢谢!

【问题讨论】:

您将视觉效果视图的框架设置为self.bounds,但将遮罩视图的框架设置为self.frame。看看是不是这个原因。 UIVisualEffectView 已知在屏蔽时有错误行为。 @LeoNatan 我尝试将两者都设置为self.boundsself.frame,但它仍然不起作用:(.... @LeoNatan 还有其他想法吗? 抱歉,现在不行。 您从哪里调用此代码,例如。 viewDidLoad 还是 viewWillAppear?如果是这样,view.frameview.bounds 将包含无效值,例如 (0, 0, 1000, 1000),因为视图尚未布局。在调试器中检查它。 【参考方案1】:

不幸的是,在 iOS 10 / Xcode 8 中使用 layer.mask 时会出现一个已知错误,它会重新屏蔽 VisualEffectViews。我在接受的答案here 中找到了一个代码示例,应该为您工作......它似乎与您的代码仅在 Swift 3 语法上有所不同(据我所知)。不过,值得仔细检查代码事件的顺序和您使用的语法,以确保您没有遗漏任何内容。

let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath
maskLayer.fillRule = kCAFillRuleEvenOdd

let borderLayer = CAShapeLayer()
borderLayer.path = circle.cgPath
borderLayer.strokeColor = UIColor.white.cgColor
borderLayer.fillColor = UIColor.clear.cgColor //Remember this line, it caused me some issues
borderLayer.lineWidth = 10

let maskView = UIView(frame: self.view.frame)
maskView.backgroundColor = UIColor.black
maskView.layer.mask = maskLayer

blur.layer.addSublayer(borderLayer)
blur.mask = maskView

您也可以在创建遮罩后尝试使用setNeedsDisplay()layoutIfNeeded() 强制视图布局。请参阅 flainez 于 8 月 4 日在苹果开发者论坛上this 线程上的评论,他说这解决了他显示蒙面 VisualEffectView 的问题。

上面的链接线程也有关于这个问题的广泛讨论、代码示例以及来自 Apple 员工的反馈和建议,“Rincewind”正在解决这个问题。如果您仍在为这个问题苦苦挣扎,我建议您通读一遍。我认为总体共识是,这个问题对于屏蔽的 VisualEffectsViews 是可以解决的,但对于尝试在视图之间转换期间使用屏蔽的 VisualEffectsViews 的开发人员来说是不可解决的。

您还可以查看this 2015 WWDC video 关于 UIVisualEffectView 的信息。

【讨论】:

以上是关于iOS 10 上的 UIVisualEffectView 蒙版的主要内容,如果未能解决你的问题,请参考以下文章

OSX 10.10 Yosemite 上的 iOS 6.1 模拟器

iOS 10 上的 UIVisualEffectView 蒙版

iOS 应用程序卡在 iOS 10.3 上的 Launch Image

在 iOS 10 上的 WKWebView 中打开 PDF 文件时启用捏合缩放手势

使用 IOS9 时,无法在 UITable 的部分标题上的 UIButtons 上触发触摸事件(IOS10 很好)

iOS 10上的ScrollView“错误”,swift 4 [重复]