Ios 如何淡入淡出UIVisualEffectView和/或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

我想淡入淡出UIVisualEffects视图,并使用UIBlurEffect:

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()
            }
        }
    }
}