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
UIVisualEffectView
dans une UIView
et de l'atténuer, sans succèsJe 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.
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:
UIVisualEffect
persistante/invariable avec une valeur alpha inférieure à 1 ne se présentera pas comme prévu/conçue par Apple; et 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.)
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.
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.
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()
} )
}
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.
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
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
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.
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.
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.
_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.
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".
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 () } } } }