Bir UIVisualEffectView ve / veya UIBlurEffect'i içeri ve dışarı nasıl soldurabilirim?


93

Bir UIBlurEffect ile bir UIVisualEffectsView'ı içeri ve dışarı soldurmak istiyorum:

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

A tarafından çağrılan bir işlevin içinde UIButtononu karartmak için normal bir animasyon kullanıyorum , aynı karartma ama .alpha = 0& hidden = true:

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

Şimdi, her iki yönde de solma iş yapar ama solma zaman bana bir hata verir dışarı :

<UIVisualEffectView 0x7fdf5bcb6e80>opaklığını canlandırması isteniyor. Bu, opaklık 1'e dönene kadar efektin bozuk görünmesine neden olur.

Soru

İçeri UIVisualEffectViewve dışarı geçişi kırmadan ve solma geçişi olmadan başarılı bir şekilde nasıl kısabilirim?

Not

  • Bunu UIVisualEffectViewbir içine koymaya UIViewve onu soldurmaya çalıştım , başarı yok

Hatayı şu şekilde önleyebilirsiniz: 1. blurEffect'e bir başlangıç ​​stili ATAMAZ. yani, var blurEffectView = UIVisualEffectView () ve ardından 2. blurEffect'i animasyon bloğunun İÇİNDE blurEffectView'e atama. 3. "blurEffect'in blurEffectView'e atanması", blurEffectView.alpha'ya yapılan ayarlamalar yerine yapılır. ** Bir başlangıç ​​değeri atasanız bile, sıfırlasanız ve sonra tekrar ekleseniz bile hata görünür. Bu nedenle, hatayı önlemenin anahtarı, efektin blurEffectView'e animasyon bloğuna kadar atanmamasıdır.
ObjectiveTC

Ayrıca, hatayı önlemek için blurEffectView'in alfa = 1.0 olması gerektiğini belirtmek gerekir. Alfa ile herhangi bir şekilde oynamak hataya neden olacaktır. Örneğin, animasyon bloğundan önce blurEffectView.alpha = 0.7'yi ayarlarsınız, ardından animationBlock'a blurEffectView.effect = blurEffect atarsınız, hata üretilir.
ObjectiveTC

Yanıtlar:


188

Bunun iOS9'da yeni olduğunu düşünüyorum, ancak artık UIVisualEffectViewbir animasyon bloğunun içindeki efektini ayarlayabilirsiniz :

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

nilKaldırmak için ayarlayın .

ÇOK ÖNEMLİ - Bunu simülatörde test ederken, bunun çalışması için simülatörünüzün Grafik Kalitesini Geçersiz Kılmayı Yüksek Kaliteye ayarladığınızdan emin olun.


1
Mükemmel çalışıyor. Teşekkürler.
Baza207

Harika! Söylediğiniz gibi, iOS 8 için çalışmıyor olsa da: /
LinusGeffarth

Tam olarak yukarıda yazdıklarım yüzünden. Yine de şimdi onayladım. @jpros
LinusGeffarth

10
Güzel bir "bulanıklaştırma" elde etmek için efekti sıfır olarak da ayarlayabilirsiniz
jpros

1
@jpros "Bulanıklaştır" ile ne demek istediğini açıklayabilir misin?
ndmeiri

19

Elma dokümantasyon (şu anda) devletler ...

UIVisualEffectView sınıfını kullanırken, 1'den küçük alfa değerlerinden kaçının.

ve

Görsel efekt görünümünde veya herhangi bir denetiminde alfa'yı 1'den küçük olarak ayarlamak, birçok efektin yanlış görünmesine veya hiç görünmemesine neden olur.

Burada bazı önemli bağlamların eksik olduğuna inanıyorum ...

Kalıcı bir görünüm için amacın 1'den küçük alfa değerlerinden kaçınmak olduğunu öneririm. Benim naçizane görüşüme göre bu, bir görünümün canlandırılması için geçerli değildir.

Demek istediğim - 1'den küçük alfa değerlerinin animasyonlar için kabul edilebilir olduğunu öneririm.

Terminal mesajı şunları belirtir:

UIVisualEffectView'den opaklığını canlandırması isteniyor. Bu, opaklık 1'e dönene kadar efektin bozuk görünmesine neden olur.

Bunu dikkatlice okursanız, etki bozulmuş gibi görünecektir . Bu varlıkla ilgili noktalarım:

  • görünen kopuş, yalnızca kalıcı bir görüş için gerçekten önemlidir - değişmeyen;
  • UIVisualEffect1'den düşük alfa değerine sahip kalıcı / değişmeyen görünüm, Apple tarafından tasarlandığı / tasarlandığı şekilde sunulmayacaktır; ve
  • terminaldeki mesaj bir hata değil, sadece bir uyarıdır.

Sorunumu çözmeme yardımcı olan @ jrturton'un yanıtını genişletmek için ekleyeceğim ...

Karartmak UIVisualEffectiçin aşağıdaki (Amaç-C) kodunu kullanın:

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

Her iki yöntemi de başarıyla kullanıyorum: effectözelliği olarak nilayarlama ve alphaözelliği olarak ayarlama 0.

Bu ayarı Not effectiçin nilayarlanırken, animasyon sonunda (daha iyi bir açıklama istemek için) "güzel flaş" yaratır alphaiçin 0sorunsuz bir geçiş oluşturur.

(Herhangi bir sözdizimi hatası varsa bana bildirin ... obj-c yazıyorum.)


Katkınız için teşekkürler. Ne demek istediğini anladım; hata benim için tam olarak bahsettiğiniz
şeyle çözüldü

15

İşte Swift 3'ü kullanarak hem iOS10 hem de önceki sürümlerde çalışan son bulduğum çözüm

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

}

Örnek bir kullanım bulmak için bu özü de kontrol edebilirsiniz .


UIViewPropertyAnimatorİOS 11'de çalışan tek şey, kullanmaktır. Bunun için teşekkürler!
LinusGeffarth

Eklemeyi unutmayın: UIKit'i içe aktar
Oleksandr

8

Yalnızca bir çözüm - UIVisualEffectViewbir konteyner görünümüne yerleştirin ve alphao konteynerin özelliğini değiştirin . Bu yaklaşım benim için iOS 9'da mükemmel çalışıyor. Görünüşe göre artık iOS 10'da çalışmıyor.


Güzel. Teşekkürler, deneyeceğim :)
LinusGeffarth

1
Örnek kod verebilir misiniz? Bu işe yaramıyor gibi görünüyor.
cnotethegr8

Benim için çalışıyor iOS 9
5hrp

@DerrickHunt Burada da aynı. bir çözüm buldun mu?
damirstuhec

2
@damirstuhec Projeniz yalnızca iOS 10 ise, UIBlurView gücünü canlandırmak için yeni UIViewPropertyAnimator sınıfını kullanabilirsiniz. Eski sürümleri desteklemeniz gerekiyorsa, yukarıdaki kodu kullanabilir ve #available anahtar sözcüğünü 10 çalıştıran cihazlar için UIViewPropertyAnimator'ı kullanmak için kullanabilirsiniz. Umarım bu yardımcı olur!
Derrick Hunt

5

Konsolda uyarı dışında görsel efektler görünümünün alfasını sorunsuz bir şekilde değiştirebilirsiniz. Görünüm, bulanık değil, kısmen saydam görünebilir. Ancak, animasyon sırasında yalnızca alfayı değiştiriyorsanız bu genellikle bir sorun oluşturmaz.

Uygulamanız bunun için kilitlenmeyecek veya reddedilmeyecek. Gerçek bir cihazda (veya sekiz) test edin. Görünüşünden ve performansından memnunsanız, sorun değil. Apple, alfa değeri 1 olan bir görsel efekt görünümünün yanı sıra görünmeyebileceği veya performans göstermeyebileceği konusunda sizi uyarıyor.


5

Statik bir temel görünümün anlık görüntüsünü alabilir ve bulanıklaştırma görünümünün opaklığına dokunmadan görüntüyü açıp kapatabilirsiniz. Bir bulanıklık ivarını varsayarsak

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

İyi bir fikir ama bu, bulanıklaştırma görünümünün altındaki statik olmayan (hareketli / hareketli) içerik için işe yaramayacak.
LinusGeffarth

@LinusG. Apple, bulanık görünüm alfa ile oynamaması gerektiğini söylüyor. Temel görünümünüzün ekran görüntülerini almak için bir CADisplayLink kullanabilir, ardından bunları bir resim görünümünde (belki yaptığınız bir - gerçek hafif) oluşturabilir ve opaklığını 0'a değiştirirken bunları üstten görünümde gösterebilirsiniz. Mümkün ama çok fazla iş.
David H

1
Bu, (şimdiye kadar) iOS 10'da istediğimi elde edebilmemin tek yoluydu - çok koyu bir bulanıklık efekti ile tam ekran üzerinde bir modal olarak kayboldu. Teşekkürler!
Graham

3

UIVisualEffectView'inizde kaybolmak istiyorsanız - ios10 için UIViewPropertyAnimator kullanın

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

o zaman yüzdeyi ayarlayabilirsiniz

[animator setFractionComplete:percent];

ios9 için alfa bileşenini kullanabilirsiniz


2
Soru, "amaç-c" değil, özellikle "hızlı" olarak etiketlenmiştir: lütfen Swift ile bir yanıt verin. Teşekkürler!
Eric Aya

1
Amaç C Kodu için teşekkürler. Listelenen başka pek çok örnek olmadığı için kullanışlı buldum.
Adam Ware

2

UIVisualEffectView'ün alfa değeri her zaman 1 olmalıdır. Arka plan renginin alfasını ayarlayarak efekti elde edebileceğinizi düşünüyorum.

Kaynak: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIVisualEffectView/index.html


Peter, lütfen arka plan renginin alfa değerini nasıl ayarlayacağınızı açıklar mısınız?
Boris Y.

@borisy örneklerde colorWithAlphaComponent:yöntemi kullanır UIColor. Yine de arka plan rengini ayarlayarak aynı etkiyi nasıl elde edeceğinizden emin değilim.
nemesis

Arka plan alfa bileşenini değiştirerek beklendiği gibi çalışmıyor
Honghao Zhang

1

Alfa 0 olan bir uiview yapıyorum ve bunun alt görünümü olarak blurview ekliyorum. Böylece onu animasyonla gizleyebilir / gösterebilir veya köşelerini yuvarlayabilirim.


1

Ve UIVisualEffectViewiçerik için ayrı animasyonlar kullanarak aşağıdaki çözümü elde ettim . Kullandığım viewWithTag()için bir başvuru için bir yöntem UIViewiçinde 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 }

Alfa'yı değiştiren tek bir animasyon tercih ederim, ancak bu hatayı önler ve aynı şekilde çalışıyor gibi görünüyor.


1

Bu sorunu yeni yaşadım ve bunun üstesinden gelme şeklim, UIVisualEffectsView'ı bir UIView'de barındırmak ve bu UIView alfa'sını canlandırmaktı.

Alfa 1.0'ın altına düşer düşmez düz beyaza dönüştü ve çok sarsıcı görünmesi dışında bu iyi çalıştı. Bunu aşmak için, UIView katman özelliğini ayarlamanız gerekir containerView.layer.allowsGroupOpacity = falseve bu, beyaz renkte yanıp sönmesini önleyecektir.

Artık görsel efektler görünümünü ve alfa özelliğini kullanarak diğer alt görünümleri içeren UIView'ı canlandırabilir / söndürebilirsiniz ve herhangi bir grafiksel hata veya bir uyarı mesajı kaydetme konusunda endişelenmenize gerek kalmaz.


0
_visualEffectView.contentView.alpha = 0;

UIVisualEffectView'ün alfa değerini değiştirmek için, _visualEffectView'ün contentView'unu değiştirmelisiniz. _VisualEffectView'ün alfa değerini değiştirirseniz, bunu alacaksınız

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

0

Genellikle, ekran üzerinde bir görünüm denetleyicisi sunduğumda ve sunum görünümü denetleyicisini bulanıklaştırmak istediğimde yalnızca bir bulanıklığı canlandırmak istiyorum. Bunu kolaylaştırmak için bir görünüm denetleyicisine blur () ve unblur () ekleyen bir uzantı:

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

Elbette, kullanıcının efekt stilini seçmesine, süreyi değiştirmesine, animasyon tamamlandığında bir şey çağırmasına, eklenen görsel efekt görünümünü bulanık olarak etiketleyerek () bulanıklığı kaldırdığınızda kaldırılan tek görünüm olmasını sağlayarak () bunu daha sağlam hale getirebilirsiniz ( ), vb, ancak şu ana kadar bunları yapmaya ihtiyaç duymadım, çünkü bu "ateş et ve unut" tipi bir operasyon olma eğilimindedir.


"ateş et ve unut" çok sevindirici! Ha
LinusGeffarth

0

@ cc'nin cevabına dayanarak uzantısını bir görünümü bulanıklaştıracak şekilde değiştirdim

uzantı UIView {

    func blur () {
        // Mevcut görünümü bulanıklaştır
        let blurView = UIVisualEffectView (çerçeve: self.bounds)
        self.addSubview (blurView)
        UIView.animate (withDuration: 0.25) {
            blurView.effect = UIBlurEffect (stil: .dark)
        }
    }

    func unblur () {
        Alt görünümlerde childView için {
            guard let effectView = childView as? UIVisualEffectView else {devam}
            UIView.animate (withDuration: 2.5, animasyonlar: {
                effectView.effect = nil
            }) {
                didFinish in
                effectView.removeFromSuperview ()
            }
        }
    }
}

0

@ Tel4tel ve @cc yanıtını iyileştirme, burada parametreler ve kısa bir açıklama içeren bir uzantı.

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

O zaman şu şekilde kullanabilirsiniz: view.blur(duration: 5.0, effect: .light) veya view.unblur(duration: 3.0)

viewDidLoad()Animasyonu geçersiz kılacağı için bunu KULLANMAYIN . Ayrıca, bir Simülatörde çalışırken, animasyonu görebilmek için grafikleri Yüksek seviyeye çevirin (Hata Ayıklama> Grafik Kalitesi Geçersiz Kılma> Yüksek Kalite).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.