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
UIVisualEffectView
in eine UIView
zu setzen und diese zu verblassen, kein ErfolgIch 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.
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:
UIVisualEffect
-Ansicht mit einem Alpha-Wert von weniger als 1 wird nicht wie von Apple beabsichtigt/entworfen angezeigt. und 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.)
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.
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.
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()
} )
}
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.
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
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
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.
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.
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.
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).
_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.
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.
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 () } } } }