简体   繁体   中英

UIVisualEffectView mask on iOS 10

I have an UIVisualEffectView and a shape ( CGPath ) that I want to view's shape to be.

I've heard that masking the UIVisualEffectView will do it.

So that what I did ( PocketSVG is an API that helps you convert SVG file to CGPath ). code:

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

It works great on iOS 9 and below but it doesn't work on iOS 10 and Xcode 8 (there is no blur, just transparent view).

Here's a link for my SVG file if someone wants to try:

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

Any idea how can I make it work on iOS 10 as well?

Thanks!

There is a known bug when using layer.mask in iOS 10 / Xcode 8 unfortunately re masking VisualEffectViews. I found a code sample in the accepted answer here that should work for you...it seems to differ from your code only by the Swift 3 syntax (as far as I could see). It could be worth worth double checking the order of code events and the syntax you are using, though, just to be sure you aren't missing anything.

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

You could also try forcing a view layout using setNeedsDisplay() and layoutIfNeeded() after creating your mask. See the comment by flainez on Aug 4th on this thread on the apple developer forums, who said that this fixed his issue with displaying a masked VisualEffectView.

The linked thread above also has extensive discussion about this issue, code samples and feedback and suggestions from an Apple employee, 'Rincewind' re fixing this issue. I would recommend reading through it if you're still struggling with this issue. I think the overall consensus is that the issue is resolvable for masked VisualEffectsViews, but was not resolvable for developers trying to use masked VisualEffectsViews during transitions between views.

You could also check out this 2015 WWDC video about UIVisualEffectView.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM