web-dev-qa-db-fra.com

Comment faire apparaître en fondu un effet UIVisualEffectView et/ou UIBlurEffect?

Je veux fondre un UIVisualEffectsView avec un UIBlurEffect:

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

J'utilise une animation normale dans une fonction appelée par une UIButton pour la fondre en dedans, idem pour les fondus en sortie mais .alpha = 0 & hidden = true:

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

Maintenant, le fondu dans les deux sens fonctionne, mais cela me donne une erreur lors du fondu out :

<UIVisualEffectView 0x7fdf5bcb6e80> est invité à animer son opacité. Cela fera apparaître l'effet brisé jusqu'à ce que l'opacité revienne à 1.

Question

Comment est-ce que je réussis à faire fondre la UIVisualEffectView sans la casser et à avoir une transition qui s'estompe?

Remarque

  • J'ai essayé de mettre la UIVisualEffectView dans une UIView et de l'atténuer, sans succès
81
LinusGeffarth

Je pense que cela est nouveau dans iOS9, mais vous pouvez maintenant définir l’effet d’une UIVisualEffectView dans un bloc d’animation: 

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

Réglez-le sur nil pour le supprimer. 

TRÈS IMPORTANT - Lorsque vous testez cela sur le simulateur, assurez-vous de définir le paramètre Priorité qualité-graphique de votre simulateur sur Haute qualité pour que cela fonctionne.

175
jrturton

La Documentation Apple (indique actuellement) ... 

Lorsque vous utilisez la classe UIVisualEffectView, évitez les valeurs alpha inférieures à 1.

et

Si vous définissez un alpha inférieur à 1 dans la vue des effets visuels ou dans l’une de ses superviews, de nombreux effets semblent incorrects ou ne sont pas affichés du tout.

_ {Je crois qu'il manque un contexte important ici ...} _

Je suggérerais que l'objectif est d'éviter les valeurs alpha inférieures à 1 pour une vue persistante. À mon humble avis, cela ne s'applique pas à l'animation d'une vue. 

Mon point - Je suggérerais que les valeurs alpha inférieures à 1 sont acceptables pour les animations.

Le message du terminal indique:

UIVisualEffectView est invité à animer son opacité. Cela fera apparaître l'effet brisé jusqu'à ce que l'opacité revienne à 1.

En lisant ceci attentivement, l’effet sera apparaître à être rompu. Je soulève deux points à ce sujet: 

  • la rupture apparente ne compte vraiment que pour un point de vue persistant - qui ne change pas;
  • une vue UIVisualEffect persistante/invariable avec une valeur alpha inférieure à 1 ne se présentera pas comme prévu/conçue par Apple; et 
  • le message dans le terminal n'est pas une erreur, mais un avertissement. 

Pour prolonger la réponse de @ jrturton ci-dessus qui m'a aidé à résoudre mon problème, j'ajouterais ...

Pour supprimer la UIVisualEffect, utilisez le code suivant (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()
} )

J'utilise avec succès les deux méthodes: en définissant la propriété effect sur nil et en définissant la propriété alpha en 0

Notez que définir effect sur nil crée un "joli flash" (à défaut d'une meilleure description) à la fin de l'animation, tandis que définir alpha sur 0 crée une transition en douceur.

(Faites-moi savoir les erreurs de syntaxe ... J'écris dans obj-c.)

17
andrewbuilder

Voici la solution que j'ai trouvée qui fonctionne à la fois sur iOS10 et les versions antérieures à l'aide de 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
            }
        }
    }

}

Vous pouvez également consulter ce Gist pour trouver un exemple d'utilisation.

12
Gunhan

Juste une solution de contournement - mettez UIVisualEffectView dans une vue de conteneur et modifiez la propriété alpha pour ce conteneur. Cette approche fonctionne parfaitement pour moi sur iOS 9. Il semble que cela ne fonctionne plus sous iOS 10.

8
beryllium

Vous pouvez prendre un instantané d’une vue statique sous-jacente et la faire fondre en fondu sans toucher à l’opacité de la vue floue. En supposant 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()
    } )
}
5
David H

Vous pouvez modifier la valeur alpha de la vue des effets visuels sans aucun problème, autre que l'avertissement affiché dans la console. La vue peut sembler simplement transparente, plutôt que floue. Mais ce n'est généralement pas un problème si vous ne faites que changer l'alpha pendant l'animation.

Votre application ne va pas se bloquer ou être rejetée pour cela. Testez-le sur un appareil réel (ou huit). Si vous êtes satisfait de son apparence et de ses performances, c'est bien. Apple vous avertit simplement que son apparence et ses performances risquent de ne pas être identiques à ceux d'une vue avec effets visuels d'une valeur alpha de 1.

4
Dave Batton

Si vous voulez vous fondre dans UIVisualEffectView - pour ios10, utilisez 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]];
    }];

alors vous pouvez définir le pourcentage

[animator setFractionComplete:percent];

pour iOS 9, vous pouvez utiliser un composant alpha 

3
kiril kiroski

L'alpha de UIVisualEffectView doit toujours être 1. Je pense que vous pouvez obtenir l'effet en définissant l'alpha de la couleur de fond.

Source: https://developer.Apple.com/library/ios/documentation/UIKit/Reference/UIVisualEffectView/index.html

2
Peter Lendvay

Je me suis retrouvé avec la solution suivante, en utilisant des animations séparées pour UIVisualEffectView et le contenu. J'ai utilisé la méthode viewWithTag() pour obtenir une référence à la UIView à l'intérieur de la 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 }

Je préférerais que l'animation simple modifie l'alpha, mais cela évite l'erreur et semble fonctionner aussi bien.

1
demian

Je viens d'avoir ce problème et la façon dont je l'ai résolu consistait à héberger UIVisualEffectsView dans un UIView et à animer l'alpha de ce dernier.

Cela a bien fonctionné, sauf que dès que l'alpha a changé en dessous de 1.0, il est devenu blanc et semblait très choquant. Afin de contourner ce problème, vous devez définir la propriété de couche UcodeView containerView.layer.allowsGroupOpacity = false afin d'éviter qu'elle ne clignote en blanc.

Maintenant, vous pouvez animer dans/masquer l'UIView contenant la vue des effets visuels et toute autre sous-vue utilisant sa propriété alpha sans avoir à vous soucier des problèmes graphiques ou de la journalisation d'un message d'avertissement.

1
user1898712

Je fais un uiview qui alpha est 0 et ajoute blurview comme sous-vue de cela. Donc, je peux cacher/montrer ou arrondir les coins avec animation.

1
Kemal Can Kaynak
_visualEffectView.contentView.alpha = 0;

Pour modifier l'alpha d'UIVisualEffectView, vous devez modifier le contentView de _visualEffectView.Si vous modifiez l'alpha de _visualEffectView, vous obtiendrez ceci 

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

En règle générale, je souhaite animer un flou lorsque je présente un contrôleur de vue sur l'écran et que le contrôleur de vue présenté est flou. Voici une extension qui ajoute blur () et unblur () à un contrôleur de vue afin de faciliter cela:

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

Vous pouvez bien sûr rendre cela plus robuste en laissant l’utilisateur choisir le style de l’effet, modifier la durée, appeler quelque chose lorsque l’animation est terminée, baliser la vue de l’effet visuel ajouté en flou () ), etc., mais je n’ai pas trouvé la nécessité de faire ces choses jusqu’à présent, car c’est plutôt du type "feu et oublie".

0
cc.

sur la base de la réponse de @ cc, j'ai modifié son extension pour rendre une vue floue.

 extension UIView {

 func blur () {
 // Estompe la vue actuelle 
 laissez blurView = UIVisualEffectView (frame: self.bounds) 
 self.addSubview (blurView) 
 UIView.animate (withDurée: 0.25) {
 blurView.effect = UIBlurEffect (style: .dark) 
 } 
 } 

 func unblur () {
 pour childView dans les sous-vues {
 gardien laisse effectView = childView as? UIVisualEffectView else {continuer} 
 UIView.animate (withDurée: 2.5, animations: {
 EffectView.effect = nil 
}) {
 didFinish in 
 effectView.removeFromSuperview () 
 } 
 } 
 } 
} 
0
Tel4tel