這篇文章針對新手向 iOS 玩家, 請老鳥自行飄過_
目前很多 iOS 新手都是通過拖拖控件, 搞搞 UI 這種方式入門的, 畢竟直觀易懂, What You See Is What You Get 的方式也很容易接受, 降低入門門檻. 可凡事都要辯證地看, 正是這種相對容易的學(xué)習(xí)方式會令你忽略很多東西.
閑話不多啥, 直接進(jìn)入主題!
首先讓我們回到最初的起點, 回到那最單純的開始. 在一個新建的 Single View Application 的空白 Main.storyboard 中拖入一個 UIButton, 好了, 大功告成! 成果如下:
你確定這不是在逗我? 這有什么好說的!!!
那么問題來了! 為什么"Button"這幾個字是藍(lán)色的?
你可能會說, 這是系統(tǒng)設(shè)定的, 跟我有什么關(guān)系? Alright! Alright! 現(xiàn)在來點兒更有趣的, 我們?yōu)檫@個 Button 加一個 image, 注意, 不是 backgroundImage.
這個要加載的 image 原來長成這個樣子, 見下圖:
如果顯示器不偏色的話, 你看到的應(yīng)該是一張黑色的圖片. 可是, 把它設(shè)置為 Button 的 image 后, 居然變成這個樣子了:
你可能會說, 我的明明是這樣的啊:
朋友, 當(dāng)心! 通過 storyboard 為 Button 設(shè)置 image 屬性后, 這個 Button 的 Type 屬性會變?yōu)?Custom, 把它改回 System 就變成藍(lán)色的了.
細(xì)心的你可能已經(jīng)發(fā)現(xiàn)了, 這個 Button 的 Type 至關(guān)重要啊, 直接影響 Button 會長成什么樣子. 沒錯, Type 為 System 時, Button 就會受某些系統(tǒng)參數(shù)的影響, 那到底是系統(tǒng)的什么東西在影響著 Button 的樣子呢?
我們的主角終于要正式登場啦! 這個會對 Button 的樣子產(chǎn)生影響的所謂的"系統(tǒng)的東西"就是 tintColor, 這是一個 UIColor 類型的屬性. 這個詞兒怎么翻譯? 算了, 還是不要糾結(jié)翻譯的問題了, 就直接稱呼它的英文名吧...
先來一個粗略的認(rèn)識, 大家可以認(rèn)為系統(tǒng)默認(rèn)的 tintColor 就是藍(lán)色的, 于是乎整個 App 中采用 System 類型的 Button 就都變藍(lán)了. 其實, 受其影響的還不只 UIButton, 回想一下, 你創(chuàng)建的 navagation controller 和 tabbar controller, 是不是導(dǎo)航欄里的東西默認(rèn)都是藍(lán)色的? 還有 slider 在滑動時露出的部分也是藍(lán)色的? 還有一些其他的控件也受其影響, 這里不再贅述了.
看來, 我們終于逮到了這個所謂的"系統(tǒng)級別"的元兇! 那問題來了, 憑什么我就一定要用系統(tǒng)設(shè)定好的藍(lán)色? 我就是要改成別的顏色, 怎么辦? 顯然對每個控件都進(jìn)行自定義是不現(xiàn)實的. 沒錯, Xcode 確實提供了畢其功于一役的利器. 如果你是用 storyboard 創(chuàng)建界面的, 那么只要在入口控制器的 File Inspector 中修改一下 Global Tint 即可, 見下圖:
修改一下試試吧, 是不是你的所有控件都變色了? 就這么簡單!
問題又來了, 如果不通過 storyboard 的方式來加載界面, 而是通過純代碼的方式來實現(xiàn)界面的要怎么辦? 至此, 終于要開始探究 tintColor 最有趣的部分了!
不知道大家有沒有仔細(xì)查看頭文件, tintColor 是 iOS7.0 引入的一個 UIView 的屬性. 再來強調(diào)一下, tintColor 是 UIView 的屬性!!! 雖然沒有說三遍, 但這一點非常重要! 這就意味著, 所有的 UI 控件都有 tintColor 這個屬性! 可是我們平時也沒注意到這個東西啊, 這是怎么回事兒?
其實, tintColor 這個東西非常神奇, 它具有繼承, 重寫, 傳播的特點.
- 繼承
只要一個 UIView 的 subview 沒有明確指定 tintColor, 那么這個 view 的 tintColor 就會被它的 subview 所繼承! 在一個 App 中, 最頂層的 view 就是 window, 因此, 只要修改 window 的 tintColor, 那么所有 view 的 tintColor 就都會跟著改變.(這種說法其實并不嚴(yán)謹(jǐn), 請耐心繼續(xù)看下去_) - 重寫
如果明確指定了某個 view 的 tintColor, 那么這個 view 就不會繼承其 superview 的 tintColor, 而且自此, 這個 view 的 subview 的 tintColor 會發(fā)生改變. - 傳播
一個 view 的 tintColor 的改變會立即向下傳播, 影響其所有的 subview, 直至它的一個 subview 明確指定了 tintColor 為止.
感覺上述三點讀起來像繞口令有沒有? 不要擔(dān)心, 通過下述例子, 希望可以幫你理清脈絡(luò).
首先在一個 ViewController 中加入三個普通的 UIView, 并且一一構(gòu)成父子關(guān)系, 即 First View 的直接 subview 為 Second View, Second View 的直接 subview 為 Third View. 然后分別在三個 UIView 中加入三個類型為 System 的 UIButton, 即 First Button 是 First View 的 subview, 與整個 Second View 平級; Second Button 是 Second View 的 subview, 與整個 Third View 平級; Third Button 是 Third View 的 subview.
此時, 由于三個 UIView 的 tintColor 都沒有明確指定, 那么它們的 tintColor 都會繼承自最頂層的 view - window - 即藍(lán)色. 好了, 既然三個 view 和三個 Button 都是 window 的 subview, 那么它們的 tintColor 就一并都變?yōu)榱怂{(lán)色.
此時, 只要改變一下 window 的 tintColor, 效果就完全不一樣了, 見下圖:
怎么樣? 這與在 storyboard 中修改 Global Tint 的效果是相同的. 同時, 這也證明了 tintColor 的改變是能夠向下傳播的. 想要達(dá)到這種效果還能怎么實現(xiàn)? 沒錯, 不需要修改 window 的 tintColor, 修改 First View 的 tintColor 也同樣奏效! 因為 tintColor 的改變是向下傳播的, 重要的事情說 N 遍!!
此時, 如果我們明確指定了 Second View 的 tintColor 會如何? 看看實際效果是不是與你設(shè)想的相同:
可以看到, First View 的 tintColor 的改變在 Second View 這一層停止傳播了. 這就是 tintColor 的重寫特點! 對 First View 來說, 它的 subview - Second View - 明確指定了 tintColor, 那么這個 Second View 就不會繼承 First View 的 tintColor, 而是采用自己的 tintColor, 因此, 作為 Second View 的 subview - Second Button 以及整個 Third View - 的 tintColor 就都改變了.
最后, 如果明確指定了 Third View 的 tintColor, 那么你就會看到一個新的世界:
怎么樣? 差不多理清 tintColor 的繼承, 重寫以及傳播是怎么回事兒了吧.
總結(jié)一下就是: 對一個 view 來說, 只要它的 tintColor 沒有明確指定, 那么它就會采用其 superview 的 tintColor. 一旦這個 view 的 tintColor 改變了, 這種改變就會一直向其 subview 傳播, 直至某個 subview 明確指定了 tintColor 為止.
此外, 在某個 view 的 tintColor 發(fā)生改變時, 這個 view 以及它所有受影響的 subview 都會調(diào)用 tintColorDidChange 方法, 所以有什么自定義操作, 都可以在這個方法中進(jìn)行.
好了, 希望大家利用 tintColor 的特點來打造五彩斑斕的界面吧!