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 10
和Xcode 8
上不起作用(没有模糊,只有透明视图)。
如果有人想尝试,这是我的SVG
文件的链接:
https://www.dropbox.com/s/mjql2bzf37vpl2r/CategoriesBar.svg?dl=0
知道如何让它在iOS 10
上也能正常工作吗?
谢谢!
【问题讨论】:
您将视觉效果视图的框架设置为self.bounds
,但将遮罩视图的框架设置为self.frame
。看看是不是这个原因。 UIVisualEffectView
已知在屏蔽时有错误行为。
@LeoNatan 我尝试将两者都设置为self.bounds
和self.frame
,但它仍然不起作用:(....
@LeoNatan 还有其他想法吗?
抱歉,现在不行。
您从哪里调用此代码,例如。 viewDidLoad
还是 viewWillAppear
?如果是这样,view.frame
和 view.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 文件时启用捏合缩放手势