Bagaimana cara memudarkan UIVisualEffectView dan / atau UIBlurEffect masuk dan keluar?

93

Saya ingin memudarkan UIVisualEffectsView dengan UIBlurEffect masuk dan keluar:

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

Saya menggunakan animasi normal dalam fungsi yang dipanggil oleh a UIButtonuntuk memudarkannya, sama untuk memudar tetapi .alpha = 0& hidden = true:

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

Sekarang, memudar di kedua arah tidak bekerja namun memberikan saya sebuah kesalahan ketika memudar keluar :

<UIVisualEffectView 0x7fdf5bcb6e80>sedang diminta untuk menghidupkan keburamannya. Ini akan menyebabkan efek tampak rusak sampai opacity kembali ke 1.

Pertanyaan

Bagaimana saya berhasil memudarkan UIVisualEffectViewmasuk dan keluar tanpa merusaknya dan mengalami transisi memudar?

Catatan

  • Saya mencoba memasukkannya UIVisualEffectViewke dalam UIViewdan memudarkan yang satu itu, tidak berhasil
LinusGeffarth
sumber
Anda dapat menghindari Kesalahan dengan: 1. TIDAK menetapkan gaya awal ke blurEffect. yaitu, var blurEffectView = UIVisualEffectView () lalu 2. menetapkan blurEffect ke blurEffectView DI DALAM blok animasi. 3. menganimasikan "penugasan blurEffect ke blurEffectView" dilakukan sebagai ganti penyesuaian untuk blurEffectView.alpha. ** Kesalahan akan muncul meskipun Anda menetapkan nilai awal, nihil, lalu menambahkannya kembali. Jadi kunci untuk mencegah kesalahan tersebut adalah dengan tidak menetapkan efek ke blurEffectView sampai animasi diblokir.
ObjectiveTC
Juga perlu disebutkan, blurEffectView harus memiliki alpha = 1.0 untuk menghindari kesalahan. Merusak alfa dengan cara apa pun akan menghasilkan kesalahan. Misalnya, sebelum animasi blok Anda mengatur blurEffectView.alpha = 0,7, kemudian di animationBlock Anda menetapkan blurEffectView.effect = blurEffect, kesalahan dihasilkan.
ObjectiveTC

Jawaban:

187

Saya pikir ini baru di iOS9, tetapi Anda sekarang dapat mengatur efek UIVisualEffectViewdi dalam blok animasi:

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

Setel niluntuk menghapus.

SANGAT PENTING - Saat mengujinya di simulator, pastikan untuk menyetel Penimpaan Kualitas Grafik simulator ke Kualitas Tinggi agar ini berfungsi.

jrturton.dll
sumber
1
Bekerja dengan sempurna. Terima kasih.
Baza207
Bagus! Seperti yang Anda katakan, tidak berfungsi untuk iOS 8: /
LinusGeffarth
Nah persis karena apa yang saya tulis di atas. Aku menyetujuinya sekarang. @jpros
LinusGeffarth
10
Anda juga dapat menyetel efek ke nihil untuk mendapatkan "blur" yang cantik
jpros
1
@jpros Maukah Anda menjelaskan apa yang Anda maksud dengan "kabur?"
ndmeiri
19

The Apple dokumentasi (saat ini) menyatakan ...

Saat menggunakan kelas UIVisualEffectView, hindari nilai alfa yang kurang dari 1.

dan

Menyetel alfa menjadi kurang dari 1 pada tampilan efek visual atau salah satu tampilan supernya menyebabkan banyak efek terlihat salah atau tidak muncul sama sekali.

Saya yakin beberapa konteks penting hilang di sini ...

Saya menyarankan bahwa maksudnya adalah untuk menghindari nilai alfa yang kurang dari 1 untuk tampilan persisten. Menurut pendapat saya, ini tidak berlaku untuk animasi tampilan.

Maksud saya - Saya menyarankan bahwa nilai alpha kurang dari 1 dapat diterima untuk animasi.

Pesan terminal menyatakan:

UIVisualEffectView diminta untuk menganimasikan opasitasnya. Ini akan menyebabkan efek tampak rusak sampai opacity kembali ke 1.

Membaca ini dengan cermat, efeknya akan tampak rusak. Poin saya tentang makhluk ini:

  • istirahat yang tampak hanya benar-benar penting untuk tampilan yang gigih - bukan berubah;
  • tampilan tetap / tidak berubah UIVisualEffectdengan nilai alfa kurang dari 1 tidak akan ditampilkan sebagaimana yang dimaksudkan / dirancang oleh Apple; dan
  • pesan di terminal bukanlah kesalahan, hanya peringatan.

Untuk memperluas jawaban @ jrturton di atas yang membantu saya memecahkan masalah saya, saya akan menambahkan ...

Untuk memudarkan UIVisualEffectgunakan kode berikut (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()
} )

Saya berhasil menggunakan kedua metode: menyetel effectproperti ke nildan menyetel alphaproperti ke 0.

Perhatikan bahwa pengaturan effectuntuk nilmenciptakan "flash bagus" (untuk menginginkan penjelasan yang lebih baik) di akhir animasi, sementara pengaturan alphauntuk 0menciptakan transisi yang mulus.

(Beri tahu saya kesalahan sintaks ... Saya menulis di obj-c.)

andrewbuilder
sumber
Terima kasih atas kontribusi Anda. Saya mengerti maksud Anda; kesalahan telah diatasi untuk saya dengan apa yang Anda sebutkan :)
LinusGeffarth
15

Inilah solusi yang akhirnya saya lakukan yang berfungsi pada iOS10 dan versi sebelumnya menggunakan 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
            }
        }
    }

}

Anda juga dapat memeriksa inti ini untuk menemukan contoh penggunaan.

Gunhan
sumber
Menggunakan the UIViewPropertyAnimatoradalah satu-satunya hal yang tampaknya berhasil di iOS 11. Terima kasih untuk ini!
LinusGeffarth
Jangan lupa untuk menambahkan: import UIKit
Oleksandr
8

Hanya solusi - masukkan UIVisualEffectViewke tampilan penampung dan ubah alphaproperti untuk penampung itu. Pendekatan itu bekerja dengan sempurna untuk saya di iOS 9. Sepertinya itu tidak lagi berfungsi di iOS 10.

berilium
sumber
Keren. Terima kasih, akan mencobanya :)
LinusGeffarth
1
Bisakah Anda memberikan kode contoh. Ini sepertinya tidak berhasil.
cnotethegr8
Bekerja untuk saya di iOS 9
jam
@DerrickHunt Sama di sini. Apakah Anda menemukan solusinya?
damirstuhec
2
@damirstuhec Jika project Anda hanya untuk iOS 10, Anda dapat menggunakan kelas UIViewPropertyAnimator baru untuk menganimasikan kekuatan UIBlurView. Jika Anda perlu mendukung versi yang lebih lama, Anda dapat menggunakan kode di atas dan menggunakan kata kunci #available untuk menggunakan UIViewPropertyAnimator untuk perangkat yang menjalankan 10. Semoga ini bisa membantu!
Derrick Hunt
5

Anda dapat mengubah alfa tampilan efek visual tanpa masalah apa pun, selain peringatan di konsol. Tampilan mungkin tampak transparan sebagian, bukan buram. Tetapi ini biasanya tidak menjadi masalah jika Anda hanya mengubah alfa selama animasi.

Aplikasi Anda tidak akan mogok atau ditolak karena ini. Uji di perangkat nyata (atau delapan). Jika Anda senang dengan tampilannya dan kinerjanya, tidak apa-apa. Apple hanya memperingatkan Anda bahwa itu mungkin tidak terlihat atau bekerja sebaik tampilan efek visual dengan nilai alfa 1.

Dave Batton
sumber
5

Anda dapat mengambil jepretan dari tampilan dasar statis, dan memudarnya masuk dan keluar tanpa menyentuh opasitas tampilan buram. Dengan asumsi ivar 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()
    } )
}
David H.
sumber
Ide bagus juga, tetapi itu tidak akan berfungsi dengan baik untuk konten non-statis (bergerak / beranimasi) di bawah tampilan blur.
LinusGeffarth
@Linus. Nah, Apple mengatakan tidak boleh bermain-main dengan tampilan blur alpha. Anda dapat menggunakan CADisplayLink untuk mengambil tangkapan layar dari tampilan dasar Anda, kemudian membuatnya dalam tampilan gambar (mungkin yang Anda lakukan - sangat ringan) - dan menampilkannya di tampilan atas sambil mengubah opasitasnya menjadi 0. Mungkin tetapi banyak kerja.
David H
1
Ini adalah satu-satunya cara (sejauh ini) saya dapat mencapai apa yang saya inginkan di iOS 10 - memudar dalam mode layar penuh, dengan efek buram yang sangat gelap. Terima kasih!
Graham
3

Jika Anda ingin memudarkan Anda UIVisualEffectView - untuk ios10 gunakan 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]];
    }];

lalu Anda bisa menyetel persen

[animator setFractionComplete:percent];

untuk ios9 Anda bisa menggunakan komponen alpha

Kiril kiroski
sumber
2
Pertanyaannya secara khusus diberi tag "swift", bukan "objektif-c": harap berikan jawaban di Swift. Terima kasih!
Eric Aya
1
Terima kasih atas Kode Objective C. Saya merasa itu berguna karena tidak banyak contoh lain yang terdaftar.
Adam Ware
2

Alpha dari UIVisualEffectView selalu harus 1. Saya rasa Anda bisa mencapai efek dengan menyetel alpha dari warna latar belakang.

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

Peter Lendvay
sumber
Peter, dapatkah Anda menjelaskan cara menyetel alpha dari warna latar belakang?
Boris Y.
@borisy menggunakan colorWithAlphaComponent:metode pada UIColorinstance. Namun, tidak yakin bagaimana cara mencapai efek yang sama dengan mengatur warna latar belakang.
musuh bebuyutan
Dengan mengubah komponen alfa latar belakang tidak bekerja seperti yang diharapkan
Honghao Zhang
1

Saya membuat uiview yang alpha-nya 0 dan menambahkan blurview sebagai subview dari itu. Jadi saya bisa menyembunyikan / menampilkan atau membulatkan sudutnya dengan animasi.

Kemal Can Kaynak
sumber
1

Saya berakhir dengan solusi berikut, menggunakan animasi terpisah untuk UIVisualEffectViewdan isinya. Saya menggunakan viewWithTag()metode untuk mendapatkan referensi ke UIViewdalam 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 }

Saya lebih suka animasi tunggal mengubah alfa, tetapi ini menghindari kesalahan dan tampaknya berfungsi dengan baik.

demian
sumber
1

Saya baru saja mengalami masalah ini dan cara saya mengatasinya adalah dengan menyimpan UIVisualEffectsView di UIView, dan menganimasikan alpha UIView itu.

Ini bekerja dengan baik, hanya saja setelah alpha berubah di bawah 1.0, berubah menjadi putih solid dan tampak sangat menggelegar. Untuk menyiasati ini, Anda harus mengatur properti lapisan UIView containerView.layer.allowsGroupOpacity = falsedan ini akan mencegahnya berkedip putih.

Sekarang Anda dapat menganimasikan masuk / memudarkan UIView yang berisi tampilan efek visual dan subview lainnya menggunakan properti alfa dan tidak perlu khawatir tentang gangguan grafis atau mencatat pesan peringatan.

pengguna1898712
sumber
0
_visualEffectView.contentView.alpha = 0;

Untuk mengubah alfa UIVisualEffectView, Anda harus mengubah contentView dari _visualEffectView. Jika Anda mengubah alfa _visualEffectView, Anda akan mendapatkan ini

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

Biasanya, saya hanya ingin menganimasikan buram saat menampilkan pengontrol tampilan di atas layar dan ingin mengaburkan pengontrol tampilan presentasi. Berikut adalah ekstensi yang menambahkan blur () dan unblur () ke pengontrol tampilan untuk memfasilitasi itu:

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

Anda tentu saja dapat membuatnya lebih kuat dengan membiarkan pengguna memilih gaya efek, memodifikasi durasi, memanggil sesuatu ketika animasi selesai, memberi tag pada tampilan efek visual yang ditambahkan dalam blur () untuk memastikan itu satu-satunya yang dihapus ketika Anda menghapus blur ( ), dll., tetapi sejauh ini saya belum merasa perlu melakukan hal-hal ini, karena ini cenderung menjadi jenis operasi "tembak dan lupakan".

cc.
sumber
"api dan lupakan" sangat bisa diterima! Ha
LinusGeffarth
0

berdasarkan jawaban @ cc, saya memodifikasi ekstensinya untuk mengaburkan tampilan

ekstensi UIView {

    func blur () {
        // Buramkan tampilan saat ini
        let blurView = UIVisualEffectView (frame: self.bounds)
        self.addSubview (blurView)
        UIView.animate (withDuration: 0,25) {
            blurView.effect = UIBlurEffect (gaya: .dark)
        }
    }

    func unblur () {
        untuk childView dalam sub-tampilan {
            jaga biarkan effectView = childView as? UIVisualEffectView else {lanjutkan}
            UIView.animate (withDuration: 2.5, animasi: {
                effectView.effect = nihil
            }) {
                didFinish in
                effectView.removeFromSuperview ()
            }
        }
    }
}
Tel4tel
sumber
0

Meningkatkan respon @ Tel4tel dan @cc, berikut adalah ekstensi dengan parameter dan penjelasan singkat.

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

Kemudian Anda dapat menggunakannya seperti: view.blur(duration: 5.0, effect: .light) atau view.unblur(duration: 3.0)

Ingatlah untuk TIDAK menggunakannya viewDidLoad()karena akan menimpa animasi. Selain itu, saat menjalankan Simulator, putar grafik ke tingkat Lebih Tinggi agar dapat melihat animasi (Debug> Penimpaan Kualitas Grafik> Kualitas Tinggi).

Rafael Díaz
sumber