Ios 如何淡入淡出UIVisualEffectView和/或UIBlurEffect?
我想淡入淡出UIVisualEffects视图,并使用UIBlurEffect:Ios 如何淡入淡出UIVisualEffectView和/或UIBlurEffect?,ios,swift,fade,uiblureffect,uivisualeffectview,Ios,Swift,Fade,Uiblureffect,Uivisualeffectview,我想淡入淡出UIVisualEffects视图,并使用UIBlurEffect: var blurEffectView = UIVisualEffectView() blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark)) 我在一个由ui按钮调用的函数中使用一个普通动画来淡入淡出,淡入淡出的效果与淡出相同,但是.alpha=0&hidden=true: blurEffectView.hidden = fals
var blurEffectView = UIVisualEffectView()
blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
我在一个由ui按钮调用的函数中使用一个普通动画来淡入淡出,淡入淡出的效果与淡出相同,但是.alpha=0
&hidden=true
:
blurEffectView.hidden = false
UIView.animate(withDuration: 1, delay: 0, options: .curveEaseOut) {
self.blurEffectView.alpha = 1
}
现在,向两个方向淡入确实有效,但淡出时会给我一个错误:
被要求设置其不透明度的动画。这将导致效果显示为中断,直到不透明度恢复为1
问题
如何成功淡入淡出UIVisualEffectView
而不中断它并进行淡入过渡
注意
- 我试图将
UIVisualEffectView
放入UIView
中,然后淡出该视图,但没有成功
UIVisualEffectView的alpha始终必须为1。我认为你可以通过设置背景色的alpha来达到这个效果
来源:除了控制台中的警告之外,您可以毫无问题地更改视觉效果视图的alpha。视图可能仅显示为部分透明,而不是模糊。但如果只是在动画期间更改alpha,这通常不是问题
你的应用不会因此崩溃或被拒绝。在真实设备(或8台)上进行测试。如果你对它的外观和性能感到满意,那就好了。苹果只是警告您,它的外观或性能可能不如alpha值为1的视觉效果视图。只是一个解决方法-将UIVisualEffectView
放入容器视图,并更改该容器的alpha
属性。这种方法在iOS 9上非常适合我。似乎它在iOS 10中不再工作。您可以拍摄静态基础视图的快照,然后淡入淡出,而无需触摸模糊视图的不透明度。假设ivar为blurView:
func addBlur() {
guard let blurEffectView = blurEffectView else { return }
//snapShot = UIScreen.mainScreen().snapshotViewAfterScreenUpdates(false)
let snapShot = self.view.snapshotViewAfterScreenUpdates(false)
view.addSubview(blurEffectView)
view.addSubview(snapShot)
UIView.animateWithDuration(0.25, animations: {
snapShot.alpha = 0.0
}, completion: { (finished: Bool) -> Void in
snapShot.removeFromSuperview()
} )
}
func removeBlur() {
guard let blurEffectView = blurEffectView else { return }
let snapShot = self.view.snapshotViewAfterScreenUpdates(false)
snapShot.alpha = 0.0
view.addSubview(snapShot)
UIView.animateWithDuration(0.25, animations: {
snapShot.alpha = 1.0
}, completion: { (finished: Bool) -> Void in
blurEffectView.removeFromSuperview()
snapShot.removeFromSuperview()
} )
}
我认为这在iOS9中是新的,但现在可以在动画块内设置UIVisualEffectView
的效果:
let overlay = UIVisualEffectView()
// Put it somewhere, give it a frame...
UIView.animate(withDuration: 0.5) {
overlay.effect = UIBlurEffect(style: .light)
}
将其设置为nil
以删除
非常重要-在模拟器上测试此功能时,确保将模拟器的图形质量覆盖设置为高质量,以使其正常工作。我最终得出以下解决方案,对UIVisualEffectView
和内容使用单独的动画。我使用viewWithTag()
方法获取对UIVisualEffectView
中UIView
的引用
let blurEffectView = UIVisualEffectView()
// Fade in
UIView.animateWithDuration(1) { self.blurEffectView.effect = UIBlurEffect(style: .Light) }
UIView.animateWithDuration(1) { self.blurEffectView.viewWithTag(1)?.alpha = 1 }
// Fade out
UIView.animateWithDuration(1) { self.blurEffectView.effect = nil }
UIView.animateWithDuration(1) { self.blurEffectView.viewWithTag(1)?.alpha = 0 }
我更喜欢单个动画更改alpha,但这避免了错误,而且似乎也能正常工作。我制作了一个alpha为0的uiview,并将blurview添加为该视图的子视图。所以我可以用动画隐藏/显示或取整它。当前状态
使用UIVisualEffectView类时,避免alpha值小于1
及
在视觉效果视图或其任何超级视图中将alpha设置为小于1会导致许多效果看起来不正确或根本不显示
我相信这里缺少一些重要的背景
我建议这样做的目的是为了避免在持久视图中alpha值小于1。依我拙见,这不适用于视图的动画
我的观点-我建议对于动画来说,小于1的alpha值是可以接受的
终端信息说明:
UIVisualEffectView被要求设置其不透明度的动画。这将导致效果显示为中断,直到不透明度恢复为1
仔细阅读此内容,效果将被破坏。我的观点是:
- 表面上的突破只对一个持久的观点才有意义——而不是改变李>
- alpha值小于1的持续/不变的
UIVisualEffect
视图将不会按照Apple的预期/设计呈现;及
- 终端中的消息不是错误,只是警告李>
为了扩展@jrturton上面帮助我解决问题的答案,我要添加
要淡出UIVisualEffect
,请使用以下(Objective-C)代码:
我成功地使用了两种方法:将effect
属性设置为nil
,并将alpha
属性设置为0
请注意,将效果设置为nil
会在动画结束时创建一个“漂亮的闪光”(因为缺少更好的描述),而将alpha
设置为0
会创建一个平滑的过渡
(让我知道任何语法错误…我用obj-c写。)
要更改UIVisualEffectView的alpha,您应该更改_visualEffectView的contentView。如果更改_visualEffectView的alpha,您将得到以下结果
<UIVisualEffectView 0x7ff7bb54b490> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.
被要求设置其不透明度的动画。这将导致效果显示为中断,直到不透明度恢复为1。
如果您想在UIVisualEffectView中淡入-对于ios10,请使用UIViewPropertyAnimator
UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:nil];
blurEffectView.frame = self.view.frame;
blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
UIView *blackUIView = [[UIView alloc]initWithFrame:self.view.frame];
[bacgroundImageView addSubview:blackUIView];
[blackUIView addSubview:blurEffectView];
UIViewPropertyAnimator *animator = [[UIViewPropertyAnimator alloc] initWithDuration:4.f curve:UIViewAnimationCurveLinear animations:^{
[blurEffectView setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
}];
然后你可以设置百分比
[animator setFractionComplete:percent];
对于ios9,您可以使用alpha组件,这是我最后提出的解决方案,它可以在iOS10和使用swift3的早期版本上运行
extension UIVisualEffectView {
func fadeInEffect(_ style:UIBlurEffectStyle = .light, withDuration duration: TimeInterval = 1.0) {
if #available(iOS 10.0, *) {
let animator = UIViewPropertyAnimator(duration: duration, curve: .easeIn) {
self.effect = UIBlurEffect(style: style)
}
animator.startAnimation()
}else {
// Fallback on earlier versions
UIView.animate(withDuration: duration) {
self.effect = UIBlurEffect(style: style)
}
}
}
func fadeOutEffect(withDuration duration: TimeInterval = 1.0) {
if #available(iOS 10.0, *) {
let animator = UIViewPropertyAnimator(duration: duration, curve: .linear) {
self.effect = nil
}
animator.startAnimation()
animator.fractionComplete = 1
}else {
// Fallback on earlier versions
UIView.animate(withDuration: duration) {
self.effect = nil
}
}
}
}
您还可以找到示例用法。通常,我只想在屏幕上显示视图控制器时设置模糊动画,并希望模糊显示视图控制器。以下是一个扩展,它将blur()和unblur()添加到视图控制器中,以便于:
extension UIViewController {
func blur() {
// Blur out the current view
let blurView = UIVisualEffectView(frame: self.view.frame)
self.view.addSubview(blurView)
UIView.animate(withDuration:0.25) {
blurView.effect = UIBlurEffect(style: .light)
}
}
func unblur() {
for childView in view.subviews {
guard let effectView = childView as? UIVisualEffectView else { continue }
UIView.animate(withDuration: 0.25, animations: {
effectView.effect = nil
}) {
didFinish in
effectView.removeFromSuperview()
}
}
}
}
当然,您可以让用户选择效果样式、修改持续时间、在动画完成时调用某些内容、在blur()中标记添加的视觉效果视图以确保在取消blur()时它是唯一一个删除的视图,等等,从而使这一点更加健壮,但我还没有发现需要执行这些操作,因为这往往是一个问题“开火并忘记”类型的操作。我刚刚遇到这个问题
extension UIVisualEffectView {
func fadeInEffect(_ style:UIBlurEffectStyle = .light, withDuration duration: TimeInterval = 1.0) {
if #available(iOS 10.0, *) {
let animator = UIViewPropertyAnimator(duration: duration, curve: .easeIn) {
self.effect = UIBlurEffect(style: style)
}
animator.startAnimation()
}else {
// Fallback on earlier versions
UIView.animate(withDuration: duration) {
self.effect = UIBlurEffect(style: style)
}
}
}
func fadeOutEffect(withDuration duration: TimeInterval = 1.0) {
if #available(iOS 10.0, *) {
let animator = UIViewPropertyAnimator(duration: duration, curve: .linear) {
self.effect = nil
}
animator.startAnimation()
animator.fractionComplete = 1
}else {
// Fallback on earlier versions
UIView.animate(withDuration: duration) {
self.effect = nil
}
}
}
}
extension UIViewController {
func blur() {
// Blur out the current view
let blurView = UIVisualEffectView(frame: self.view.frame)
self.view.addSubview(blurView)
UIView.animate(withDuration:0.25) {
blurView.effect = UIBlurEffect(style: .light)
}
}
func unblur() {
for childView in view.subviews {
guard let effectView = childView as? UIVisualEffectView else { continue }
UIView.animate(withDuration: 0.25, animations: {
effectView.effect = nil
}) {
didFinish in
effectView.removeFromSuperview()
}
}
}
}
extension UIView {
func blur() {
// Blur out the current view
let blurView = UIVisualEffectView(frame: self.bounds)
self.addSubview(blurView)
UIView.animate(withDuration:0.25) {
blurView.effect = UIBlurEffect(style: .dark)
}
}
func unblur() {
for childView in subviews {
guard let effectView = childView as? UIVisualEffectView else { continue }
UIView.animate(withDuration: 2.5, animations: {
effectView.effect = nil
}) {
didFinish in
effectView.removeFromSuperview()
}
}
}
}
extension UIView {
// Perform a blur animation in the whole view
// Effect tone can be .light, .dark, .regular...
func blur(duration inSeconds: Double, effect tone: UIBlurEffectStyle) {
let blurView = UIVisualEffectView(frame: self.bounds)
self.addSubview(blurView)
UIView.animate(withDuration: inSeconds) {
blurView.effect = UIBlurEffect(style: tone)
}
}
// Perform an unblur animation in the whole view
func unblur(duration inSeconds: Double) {
for childView in subviews {
guard let effectView = childView as? UIVisualEffectView else { continue
}
UIView.animate(withDuration: inSeconds, animations: {
effectView.effect = nil
}){
didFinish in effectView.removeFromSuperview()
}
}
}
}