wake-up-neo.net

Wie blendet man UIVisualEffectView und/oder UIBlurEffect ein und aus?

Ich möchte eine UIVisualEffectsView mit einem UIBlurEffect ein- und ausblenden:

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

Ich benutze eine normale Animation innerhalb einer Funktion, die von einer UIButton aufgerufen wird, um sie einzublenden, ebenso für das Ausblenden, aber .alpha = 0 & hidden = true:

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

Nun funktioniert das Fading in beide Richtungen, aber es gibt einen Fehler beim Fading out :

<UIVisualEffectView 0x7fdf5bcb6e80> wird aufgefordert, seine Deckkraft zu animieren. Dadurch wird der Effekt so lange zerbrochen, bis die Deckkraft wieder 1 ist.

Frage

Wie kann ich UIVisualEffectView erfolgreich ein- und ausblenden, ohne dass brechen und ein Übergang verblasst?

Hinweis

  • Ich habe versucht, die UIVisualEffectView in eine UIView zu setzen und diese zu verblassen, kein Erfolg
81
LinusGeffarth

Ich denke, das ist neu in iOS9, aber Sie können jetzt den Effekt einer UIVisualEffectView innerhalb eines Animationsblocks einstellen: 

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

Legen Sie zum Entfernen nil fest. 

SEHR WICHTIG - Wenn Sie dies im Simulator testen, stellen Sie sicher, dass der Grafikqualitäts-Override Ihres Simulators auf Hohe Qualität gesetzt ist, damit dies funktioniert.

175
jrturton

Die Apple-Dokumentation gibt (derzeit) an ... 

Vermeiden Sie bei der Verwendung der UIVisualEffectView-Klasse Alpha-Werte, die kleiner als 1 sind.

und

Wenn Sie das Alpha in der Sicht der visuellen Effekte oder einer der Superviews auf unter 1 setzen, wirken viele Effekte falsch oder werden überhaupt nicht angezeigt.

Ich glaube, hier fehlt ein wichtiger Kontext ...

Ich würde vorschlagen, dass die Absicht ist, Alpha-Werte zu vermeiden, die für eine dauerhafte Ansicht kleiner als 1 sind. Meiner bescheidenen Meinung nach gilt dies nicht für die Animation einer Ansicht. 

Mein Punkt - ich würde vorschlagen, dass Alpha-Werte unter 1 für Animationen akzeptabel sind.

Die Terminal-Nachricht lautet:

UIVisualEffectView wird aufgefordert, seine Deckkraft zu animieren. Dadurch wird der Effekt so lange zerbrochen, bis die Deckkraft wieder 1 ist.

Wenn Sie dies sorgfältig lesen, wird der Effekt erscheinen gebrochen. Ich mache zwei Punkte dazu: 

  • der scheinbare Bruch ist nur für eine dauerhafte Sicht von Belang - und ändert sich nicht.
  • eine dauerhafte/unveränderliche UIVisualEffect-Ansicht mit einem Alpha-Wert von weniger als 1 wird nicht wie von Apple beabsichtigt/entworfen angezeigt. und 
  • die Meldung im Terminal ist kein Fehler, sondern nur eine Warnung. 

Um die Antwort von @ jrturton zu erweitern, die mir geholfen hat, mein Problem zu lösen, würde ich hinzufügen ...

Um die UIVisualEffect auszublenden, verwenden Sie den folgenden Code (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()
} )

Ich verwende erfolgreich beide Methoden: Setzen der effect-Eigenschaft auf nil und der alpha-Eigenschaft auf 0

Wenn Sie effect auf nil setzen, wird am Ende der Animation ein "Nice Flash" (der besseren Beschreibung halber) erstellt, während Sie durch alpha auf 0 einen glatten Übergang festlegen.

(Lass mich irgendwelche Syntaxfehler wissen ... ich schreibe in obj-c.)

17
andrewbuilder

Hier ist die Lösung, die am Ende auf iOS10 und früheren Versionen mit Swift 3 funktioniert

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

}

Sie können auch diese Gist überprüfen , um eine Beispielnutzung zu finden.

12
Gunhan

Nur eine Problemumgehung: Fügen Sie UIVisualEffectView in eine Containeransicht ein und ändern Sie die alpha-Eigenschaft für diesen Container. Dieser Ansatz funktioniert unter iOS 9 perfekt für mich. Anscheinend funktioniert er nicht mehr unter iOS 10.

8
beryllium

Sie können eine Momentaufnahme einer statischen zugrunde liegenden Ansicht machen und diese ein- und ausblenden, ohne die Deckkraft der Unschärfeansicht zu berühren. Angenommen, ein ivar of 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

Sie können das Alpha der Ansicht für visuelle Effekte mit Ausnahme der Warnung in der Konsole problemlos ändern. Die Ansicht kann einfach als teilweise transparent und nicht als verschwommen erscheinen. Dies ist jedoch normalerweise kein Problem, wenn Sie das Alpha während der Animation ändern.

Ihre App wird dafür nicht abstürzen oder abgelehnt. Testen Sie es auf einem echten Gerät (oder acht). Wenn Sie mit dem Aussehen und der Leistung zufrieden sind, ist es in Ordnung. Apple warnt Sie nur, dass es möglicherweise nicht so aussieht wie eine visuelle Effektansicht mit einem Alpha-Wert von 1.

4
Dave Batton

Wenn Sie UIVisualEffectView einblenden möchten, verwenden Sie UIViewPropertyAnimator für ios10

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

dann kannst du prozent einstellen

[animator setFractionComplete:percent];

für iOS9 können Sie die Alpha-Komponente verwenden 

3
kiril kiroski

Das Alpha des UIVisualEffectView muss immer 1 sein. Ich denke, Sie können den Effekt erzielen, indem Sie das Alpha der Hintergrundfarbe einstellen.

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

2
Peter Lendvay

Am Ende kam die folgende Lösung, die separate Animationen für UIVisualEffectView und den Inhalt verwendete. Ich habe die viewWithTag()-Methode verwendet, um einen Verweis auf die UIView in der UIVisualEffectView zu erhalten.

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 }

Ich würde es vorziehen, wenn die einzelne Animation das Alpha ändert, aber dies vermeidet den Fehler und scheint genauso gut zu funktionieren.

1
demian

Ich hatte gerade dieses Problem und so kam ich dazu, die UIVisualEffectsView in einer UIView unterzubringen und das Alpha von UIView zu animieren.

Das funktionierte gut, nur dass sich das Alpha, sobald sich der Wert unter 1,0 geändert hatte, in ein durchgehendes Weiß verwandelte und sehr unangenehm wirkte. Um dies zu umgehen, müssen Sie die Layer-Eigenschaft containerView.layer.allowsGroupOpacity = false des UIView festlegen. Dadurch wird verhindert, dass es weiß blinkt.

Jetzt können Sie die UIView mit der Ansicht für visuelle Effekte und andere Unteransichten mithilfe der Alpha-Eigenschaft animieren bzw. ausblenden. Sie müssen sich keine Sorgen um grafische Störungen oder das Protokollieren einer Warnmeldung machen.

1
user1898712

Ich mache eine Übersicht, die Alpha ist 0 und füge Blurview als Unteransicht hinzu. So kann ich es mit Animation verstecken/anzeigen oder Ecken runden.

1

Hier finden Sie eine Erweiterung mit Parametern und einer kurzen Erläuterung zur Verbesserung der @ Tel4tel- und @cc-Antwort.

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

Dann können Sie es wie folgt verwenden: view.blur(duration: 5.0, effect: .light) oder view.unblur(duration: 3.0)

Denken Sie daran, es NICHT in viewDidLoad() zu verwenden, da es die Animation überschreibt. Wenn Sie mit einem Simulator arbeiten, schalten Sie die Grafik auf die höhere Stufe, um die Animation sehen zu können (Debug> Grafikqualität überschreiben> Hohe Qualität).

0
Rafael Díaz
_visualEffectView.contentView.alpha = 0;

Um das Alpha von UIVisualEffectView zu ändern, sollten Sie die contentView von _visualEffectView ändern. Wenn Sie das Alpha von _visualEffectView ändern, wird dies angezeigt 

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

Normalerweise möchte ich eine Unschärfe nur animieren, wenn ich einen View-Controller auf dem Bildschirm präsentiere und den präsentierenden View-Controller verwischen möchte. Hier ist eine Erweiterung, die einem View-Controller Blur () und Unblur () hinzufügt, um dies zu erleichtern:

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

Sie können dies natürlich robuster gestalten, indem Sie den Benutzer den Effektstil auswählen, die Dauer ändern und nach Abschluss der Animation etwas anrufen. ) usw., aber ich habe bisher noch keine Notwendigkeit gefunden, diese Dinge zu tun, da dies eine Art "Feuer und Vergessen" ist.

0
cc.

basierend auf der Antwort von @ cc habe ich seine Erweiterung geändert, um eine Ansicht zu verwischen

 Erweiterung UIView {

 func blur () {
 // Aktuelle Ansicht verwischen 
 Lassen Sie blurView = UIVisualEffectView (Frame: self.bounds) 
 self.addSubview (blurView) 
 UIView.animate (withDuration: 0.25) {
 blurView.effect = UIBlurEffect (style: .dark) 
 } 
 } 

 func unblur () {
 für childView in Unteransichten {
 guard let effectView = childView as? UIVisualEffectView else {fortsetzen} 
 UIView.animate (withDuration: 2.5, Animationen: {
 EffectView.effect = nil 
}) {
 didFinish in 
 effectView.removeFromSuperview () 
 } 
 } 
 } 
} 
0
Tel4tel