ios swift fade uiblureffect uivisualeffectview

ios - ¿Cómo desvanecer un UIVisualEffectView y/o UIBlurEffect dentro y fuera?



swift fade (15)

Quiero desvanecer un UIVisualEffectsView con un UIBlurEffect dentro y fuera:

var blurEffectView = UIVisualEffectView() blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))

Uso una animación normal dentro de una función llamada por un UIButton para UIButton , lo mismo para desvanecerse pero .alpha = 0 & hidden = true :

blurEffectView.hidden = false UIView.animate(withDuration: 1, delay: 0, options: .curveEaseOut) { self.blurEffectView.alpha = 1 }

Ahora, el desvanecimiento en ambas direcciones funciona, pero me da un error al desvanecerme:

Se le pide a <UIVisualEffectView 0x7fdf5bcb6e80> que anime su opacidad. Esto hará que el efecto aparezca roto hasta que la opacidad vuelva a 1.

Pregunta

¿Cómo puedo desvanecer con éxito el UIVisualEffectView dentro y fuera sin romperlo y tener una transición de desvanecimiento?

Nota

  • Traté de poner el UIVisualEffectView en un UIView y desvanecerlo, sin éxito

Acabo de tener este problema y la forma en que lo solucioné fue alojar el UIVisualEffectsView en una UIView y animar el alfa de UIView.

Esto funcionó bien, excepto que tan pronto como el alfa cambió por debajo de 1.0, se volvió blanco sólido y parecía muy discordante. Para evitar esto, debe establecer la propiedad de capa de UIView containerView.layer.allowsGroupOpacity = false y esto evitará que parpadee en blanco.

Ahora puede animar / desvanecer la vista UIView que contiene la vista de efectos visuales y cualquier otra subvista usando su propiedad alfa y no tener que preocuparse por ningún problema gráfico o por registrar un mensaje de advertencia.


Aquí está la solución que terminé que funciona tanto en iOS10 como en versiones anteriores usando Swift 3

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

También puede consultar esta esencia para encontrar un ejemplo de uso.


Creo que esto es nuevo en iOS9, pero ahora puede configurar el efecto de un UIVisualEffectView dentro de un bloque de animación:

let overlay = UIVisualEffectView() // Put it somewhere, give it a frame... UIView.animate(withDuration: 0.5) { overlay.effect = UIBlurEffect(style: .light) }

Póngalo en nil para eliminarlo.

MUY IMPORTANTE: al probar esto en el simulador, asegúrese de configurar la anulación de calidad de gráficos de su simulador en Alta calidad para que esto funcione.



Hago una uiview que alpha es 0 y agrego blurview como subview de eso. Entonces puedo ocultar / mostrar o redondearlo con animación.


La documentación de Apple (actualmente) establece ...

Cuando utilice la clase UIVisualEffectView, evite los valores alfa que sean inferiores a 1.

y

Establecer el alfa en menos de 1 en la vista de efectos visuales o en cualquiera de sus supervistas hace que muchos efectos se vean incorrectos o no aparezcan en absoluto.

Creo que falta un contexto importante aquí ...

Sugeriría que la intención es evitar valores alfa inferiores a 1 para una vista persistente. En mi humilde opinión, esto no se aplica a la animación de una vista.

Mi punto: sugeriría que los valores alfa inferiores a 1 son aceptables para las animaciones.

El mensaje del terminal dice:

Se le está pidiendo a UIVisualEffectView que anime su opacidad. Esto hará que el efecto aparezca roto hasta que la opacidad vuelva a 1.

Leyendo esto cuidadosamente, el efecto parecerá estar roto. Mis puntos sobre este ser:

  • la ruptura aparente solo es realmente importante para una visión que es persistente, no cambiante;
  • una vista UIVisualEffect persistente / inmutable con un valor alfa inferior a 1 no se presentará según lo previsto / diseñado por Apple; y
  • El mensaje en el terminal no es un error, solo una advertencia.

Para ampliar la respuesta de @ jrturton anterior que me ayudó a resolver mi problema, agregaría ...

Para desvanecer el efecto UIVisualEffect use el siguiente código (Objective-C):

UIView.animateWithDuration(1.0, animations: { // EITHER... self.blurEffectView.effect = UIBlurEffect(nil) // OR... self.blurEffectView.alpha = 0 }, completion: { (finished: Bool) -> Void in self.blurEffectView.removeFromSuperview() } )

Utilizo con éxito ambos métodos: establecer la propiedad del effect en nil y establecer la propiedad alpha en 0 .

Tenga en cuenta que establecer el effect en nil crea un "buen flash" (a falta de una mejor descripción) al final de la animación, mientras que establecer el alpha en 0 crea una transición suave.

(Avíseme cualquier error de sintaxis ... escribo en obj-c.)


Mejorando la respuesta @ Tel4tel y @cc, aquí hay una extensión con parámetros y una breve explicación.

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

Luego puede usarlo como: view.blur(duration: 5.0, effect: .light) o view.unblur(duration: 3.0)

Recuerde NO usarlo en viewDidLoad() ya que anulará la animación. Además, cuando se ejecuta en un simulador, gire los gráficos al nivel superior para poder ver la animación (depuración> anulación de calidad de gráficos> alta calidad).


Por lo general, solo quiero animar un desenfoque cuando presento un controlador de vista sobre la pantalla y quiero desenfocar el controlador de vista de presentación. Aquí hay una extensión que agrega blur () y unblur () a un controlador de vista para facilitar eso:

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

Por supuesto, puede hacer que esto sea más robusto permitiendo que el usuario elija el estilo del efecto, modifique la duración, llame a algo cuando se complete la animación, etiquete la vista del efecto visual agregado en desenfoque () para asegurarse de que sea el único eliminado al desenfocar ( ), etc., pero no he encontrado la necesidad de hacer estas cosas hasta ahora, ya que esto tiende a ser un tipo de operación de "disparar y olvidar".


Puede cambiar el alfa de la vista de efectos visuales sin ningún problema, aparte de la advertencia en la consola. La vista puede aparecer simplemente como parcialmente transparente, en lugar de borrosa. Pero esto generalmente no es un problema si solo está cambiando el alfa durante la animación.

Su aplicación no se bloqueará o será rechazada por esto. Pruébelo en un dispositivo real (u ocho). Si está contento con su aspecto y rendimiento, está bien. Apple solo te advierte que puede no verse o funcionar tan bien como una vista de efectos visuales con un valor alfa de 1.


Puede tomar una instantánea de una vista subyacente estática y desvanecerla sin tocar la opacidad de la vista borrosa. Suponiendo un ivar de 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() } ) }


Si desea desvanecerse en usted UIVisualEffectView - para ios10 use 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]]; }];

entonces puedes establecer el porcentaje

[animator setFractionComplete:percent];

para ios9 puedes usar el componente alfa


Solo una solución: coloque UIVisualEffectView en una vista de contenedor y cambie alpha propiedad alpha de ese contenedor. Ese enfoque funciona perfectamente para mí en iOS 9. Parece que ya no funciona en iOS 10.


Terminé con la siguiente solución, usando animaciones separadas para UIVisualEffectView y los contenidos. viewWithTag() método viewWithTag() para obtener una referencia a UIView dentro de UIVisualEffectView .

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 }

Preferiría que la animación única cambie el alfa, pero esto evita el error y parece funcionar igual de bien.


basado en la respuesta de @ cc, modifiqué su extensión para difuminar una vista

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


_visualEffectView.contentView.alpha = 0;

Para cambiar el alfa de UIVisualEffectView, debe cambiar el contentView de _visualEffectView. Si cambia el alfa de _visualEffectView, obtendrá esto

<UIVisualEffectView 0x7ff7bb54b490> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.