UIVisualEffectView是從iOS 8開(kāi)始提供的控件,功能是創(chuàng)建毛玻璃(Blur)效果,也就是實(shí)現(xiàn)模糊效果。
從iOS 7系統(tǒng)開(kāi)始,蘋(píng)果改變了App的UI風(fēng)格和動(dòng)畫(huà)效果,例如導(dǎo)航欄出現(xiàn)在屏幕上的效果。尤其是蘋(píng)果在iOS 7中使用了全新的霧玻璃效果(模糊特效)。不僅僅是導(dǎo)航欄,通知中心和控制中心也采用了這個(gè)特殊的視覺(jué)效果。但是蘋(píng)果并沒(méi)有在SDK中放入這個(gè)特效,程序員不得不使用自己的方法模擬這個(gè)效果,一直到iOS 8的出現(xiàn)。在iOS 8中,SDK中終于正式加入了這個(gè)特性,不但讓程序員易于上手,而且性能表現(xiàn)也很優(yōu)秀,蘋(píng)果將之稱(chēng)為VisualEffects。在iOS系統(tǒng)中,通過(guò)控件UIVisualEffectView可以創(chuàng)建毛玻璃效果,也就是實(shí)現(xiàn)模糊效果。
UIVisualEffectView基礎(chǔ)
Visual Effects是一整套視覺(jué)特效,包括UIBlurEffect和UIVibrancyEffect。這兩者都是UIVisualEffect的子類(lèi),前者允許在應(yīng)用程序中動(dòng)態(tài)地創(chuàng)建實(shí)時(shí)的霧玻璃效果,而后者則允許在霧玻璃上“寫(xiě)字”。
要想創(chuàng)建一個(gè)特殊效果(如Blur效果),可以創(chuàng)建一個(gè)UIVisualEffectView視圖對(duì)象,這個(gè)對(duì)象提供了一種簡(jiǎn)單的方式來(lái)實(shí)現(xiàn)復(fù)雜的視覺(jué)效果??梢园堰@個(gè)對(duì)象看作是效果的一個(gè)容器,實(shí)際的效果會(huì)影響到該視圖對(duì)象底下的內(nèi)容,或者添加到該視圖對(duì)象的contentView中的內(nèi)容。
下面舉個(gè)例子來(lái)看看如果使用UIVisualEffectView。
let bgView: UIImageView = UIImageView(image: UIImage(named: "visual"))
bgView.frame = self.view.bounds
self.view.addSubview(bgView)
let blurEffect: UIBlurEffect = UIBlurEffect(style: .Light)
let blurView: UIVisualEffectView = UIVisualEffectView(effect: blurEffect)
blurView.frame = CGRect(x: 50, y: 50, width: self.view.frame.width - 100, height: 200)
self.view.addSubview(blurView)

上述代碼的功能是在當(dāng)前視圖控制器上添加了一個(gè)UIImageView作為背景圖。然后在視圖的一小部分中使用了毛玻璃效果。由此可見(jiàn),UIVisualEffectView是非常簡(jiǎn)單的。需要注意是的,不應(yīng)該直接將子視圖添加到UIVisualEffectView視圖中,而是應(yīng)該添加到UIVisualEffectView對(duì)象的contentView中。
另外,盡量避免將UIVisualEffectView對(duì)象的alpha值設(shè)置為小于1.0的值,因?yàn)閯?chuàng)建半透明的視圖會(huì)導(dǎo)致系統(tǒng)在離屏渲染時(shí)去對(duì)UIVisualEffectView對(duì)象及所有的相關(guān)的子視圖做混合操作。這不但消耗CPU/GPU,也可能會(huì)導(dǎo)致許多效果顯示不正確或者根本不顯示。
初始化一個(gè)UIVisualEffectView對(duì)象的方法是UIVisualEffectView(effect: blurEffect),其定義如下。
init(effect effect: UIVisualEffect)
這個(gè)方法的參數(shù)是一個(gè)UIVisualEffect對(duì)象。查看官方文檔可以看到,在UIKit中定義了幾個(gè)專(zhuān)門(mén)用來(lái)創(chuàng)建視覺(jué)特效的類(lèi),它們分別是UIVisualEffect、UIBlurEffect和UIVibrancyEffect。它們的繼承層次如下所示。
NSObject
| -- UIVisualEffect
| -- UIBlurEffect
| -- UIVibrancyEffect
UIVisualEffect是一個(gè)繼承自NSObject的創(chuàng)建視覺(jué)效果的基類(lèi),然而這個(gè)類(lèi)除了繼承自NSObject的屬性和方法外,沒(méi)有提供任何新的屬性和方法。其主要目的是用于初始化UIVisualEffectView,在這個(gè)初始化方法中可以傳入U(xiǎn)IBlurEffect或者UIVibrancyEffect對(duì)象。
一個(gè)UIBlurEffect對(duì)象用于將毛玻璃效果應(yīng)用于UIVisualEffectView視圖下面的內(nèi)容,如上面的示例所示。不過(guò),這個(gè)對(duì)象的效果并不影響UIVisualEffectView對(duì)象contentView中的內(nèi)容。
UIBlurEffect主要定義了3種效果,這些效果由枚舉UIBlurEffectStyle來(lái)確定,該枚舉的定義如下。
enum UIBlurEffectStyle : Int {
case ExtraLight
case Light
case Dark
}
其主要功能是根據(jù)色調(diào)來(lái)確定特效視圖與底部視圖的混合。
Vibrancy效果
Vibrancy效果是一種專(zhuān)門(mén)應(yīng)用在模糊效果上的特殊效果。它會(huì)在模糊效果的基礎(chǔ)上留下一些特殊的空洞,使得這些地方上的內(nèi)容看起來(lái)更加生動(dòng)。可以想象一下霧玻璃效果,它就好像是冬天的時(shí)候,你在玻璃上哈氣。原本透明的玻璃哈上氣后,會(huì)結(jié)上一層水汽,看起來(lái)就像是“霧玻璃”一樣。如果你伸手在這層水汽上寫(xiě)字,則會(huì)在霧氣上留下明顯的字跡,這就是Vibrancy效果。
在iOS應(yīng)用中,可以使用Visual Effect View來(lái)實(shí)現(xiàn)Vibrancy效果。Vibrancy效果使用Object Library中的“Visual Effect Views with Blur andVibrancy”來(lái)實(shí)現(xiàn)。從名稱(chēng)上看,“Visual EffectViews with Blur and Vibrancy”包括了兩個(gè)VisualEffect View:一個(gè)Blur Visual Effect View和一個(gè)Vibrancy Visual Effect View。事實(shí)上也是這樣的,Vibrancy效果并不能單獨(dú)應(yīng)用,它必須應(yīng)用到Blur效果之上。我們可以這樣理解:Vibrancy效果是一種“霧玻璃寫(xiě)字”的效果,因此只能先有了“霧玻璃”的情況下才能寫(xiě)字。
與UIBlurEffect不同的是,UIVibrancyEffect主要用于放大和調(diào)整UIVisualEffectView視圖下面內(nèi)容的顏色,同時(shí)讓UIVisualEffectView的contentView中的內(nèi)容看起來(lái)更加生動(dòng)。通常UIVibrancyEffect對(duì)象是與UIBlurEffect一起使用,主要用于處理在UIBlurEffect特效上的一些顯示效果。接上面的代碼,看看在模糊視圖上添加一些新特效的方法,例如:
let vibrancyView: UIVisualEffectView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: blurEffect))
vibrancyView.frame = blurView.bounds
vibrancyView.translatesAutoresizingMaskIntoConstraints = false
blurView.contentView.addSubview(vibrancyView)
let label: UILabel = UILabel()
label.frame = CGRect(x: 10, y: 75, width: 250, height: 50)
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Vibrancy Effect"
label.font = UIFont(name: "HelveticaNeue-Bold", size: 30)
label.textAlignment = .center
label.textColor = UIColor.white
vibrancyView.contentView.addSubview(label)

特效vibrancy取決于顏色值,所有添加到contentView的子視圖都必須實(shí)現(xiàn)tintColorDidChange方法并更新自己。需要注意的是,我們使用UIVibrancyEffect(forBlurEffect:)方法創(chuàng)建UIVibrancyEffect時(shí),參數(shù)blurEffect必須是我們想加效果的那個(gè)blurEffect,否則可能不是我們想要的效果。
另外,UIVibrancyEffect還提供了一個(gè)類(lèi)方法notificationCenterVibrancyEffect,其聲明如下。
class func notificationCenterVibrancyEffect() -> UIVibrancyEffect!
這個(gè)方法創(chuàng)建一個(gè)用于通知中心的Today擴(kuò)展的vibrancy特效。
摘自《Objective-C應(yīng)用開(kāi)發(fā)全程實(shí)錄》