Swift主題色頂級(jí)解決方案
一、常規(guī)主題色使用點(diǎn)
應(yīng)用在發(fā)布前都會(huì)對(duì)主題色進(jìn)行設(shè)置,以統(tǒng)一應(yīng)用的風(fēng)格(可能有多套主題)。在主題色設(shè)置上有幾個(gè)方面,如下:
1. TabBar部分,設(shè)置圖片高亮、文本高度顏色
2. NavigationBar部分,設(shè)置導(dǎo)航欄顏色及字體顏色
3. 應(yīng)用標(biāo)簽等,設(shè)置字體的顏色
4. 應(yīng)用圖片主題色
主題色的設(shè)置點(diǎn),大體從上面四個(gè)方面著手,圖片的主題色我們可通過圖片更換的方式進(jìn)行處理。而通過代碼來處理的 1-3 條,有著不同的處理方法。大家常規(guī)處理方法如下:
步驟一:變化分離
1. 利用Swift擴(kuò)展語法擴(kuò)展UIColor,將應(yīng)用主題色在擴(kuò)展中統(tǒng)一處理(適合單一主題色)
2. 將主題色的配置寫入文件中,由相應(yīng)邏輯進(jìn)行解析。此方法將主題色邏輯封裝成主題色管理類(適合多套主題)
步驟二:離散使用上步封裝的類
1.在任何使用主題色的地方,使用擴(kuò)展中的UIColor方法來設(shè)置,一般包括背景色,文字顏色等
這里給出UIColor的擴(kuò)展
- extension UIColor {
- //主題色
- class func applicationMainColor() -> UIColor {
- return UIColor(red: 238/255, green: 64/255, blue: 86/255, alpha:1)
- }
- //第二主題色
- class func applicationSecondColor() -> UIColor {
- return UIColor.lightGrayColor()
- }
- //警告顏色
- class func applicationWarningColor() -> UIColor {
- return UIColor(red: 0.1, green: 1, blue: 0, alpha: 1)
- }
- //鏈接顏色
- class func applicationLinkColor() -> UIColor {
- return UIColor(red: 59/255, green: 89/255, blue: 152/255, alpha:1)
- }
- }
二、TabBar主題色設(shè)置
很多應(yīng)用中,默認(rèn)情況下都使用了TabBar控件,但是TabBar主題色等設(shè)置根據(jù)使用情況的不同,設(shè)置起來也不一樣。代碼創(chuàng)建比較靈活,更改主題色比較容易。而使用了Xib/Storyboard也是有辦法做統(tǒng)一處理的,如下,迭代更改TabBar默認(rèn)字體顏色
- func configTabBar() {
- let items = self.tabBar.items
- for item in items as [UITabBarItem] {
- let dic = NSDictionary(object: UIColor.applicationMainColor(),
- forKey: NSForegroundColorAttributeName)
- item.setTitleTextAttributes(dic,
- forState: UIControlState.Selected)
- }
- }
設(shè)置TabBar圖片及文字默認(rèn)選中顏色
self.tabBar.selectedImageTintColor = UIColor.applicationMainColor()
Tips注意事項(xiàng)
Changing this property’s value provides visual feedback in the user interface, including the running of any associated animations. The selected item displays the tab bar item’s selectedImage image, using the tab bar’s selectedImageTintColor value. To prevent system coloring of an item, provide images using the UIImageRenderingModeAlwaysOriginal rendering mode.
在一些情況,正常狀態(tài)為白色圖片時(shí),真機(jī)測(cè)試時(shí),白色圖片會(huì)出現(xiàn)偏色(顯示結(jié)果為灰色),這是因?yàn)橄到y(tǒng)默認(rèn)著色導(dǎo)致的,在創(chuàng)建UITabBarItem時(shí),可通過使用UIImageRenderingModeAlwaysOriginal避免。示例代碼如下:
- let imageNormal = UIImage(contentsOfFile: "imageNormal")?.
- imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
- let imageSelected = UIImage(contentsOfFile: "imageSelected")
- let tabBarItem = UITabBarItem(title: "title",
- image: imageNormal,
- selectedImage: imageSelected
三、一勞永逸,利用Hook原理通設(shè)NavigationBar顏色
iOS應(yīng)用中,NavigationBar十分常用,它的使用主要包括以下兩個(gè)場(chǎng)景
1. 代碼直接構(gòu)建
2. Xib/Storyboard構(gòu)建
如果是純代碼構(gòu)建的時(shí)候,比較簡(jiǎn)單,直接使用UIColor的擴(kuò)展來設(shè)置顏色。實(shí)際項(xiàng)目中,有些界面是通過Xib/Storyboard來創(chuàng)建的,有些是代碼寫的,但這也難不到大家,使用繼承。創(chuàng)建一個(gè)繼承自UINavigationController的子類,通過這個(gè)子類來統(tǒng)一設(shè)置主題色。然后告訴項(xiàng)目中的所有人,強(qiáng)制使用UINavigationController子類,包括Xib/Storyboard等。問題是舊項(xiàng)目怎么辦,這種強(qiáng)制要求可以工作,有沒有一個(gè)更好的辦法,讓所有人正常使用UINavigationController,而在神不知鬼不覺的情況下,通設(shè)所有NavigationBar呢? 先上代碼,再解釋
1.創(chuàng)建一個(gè)UIViewController的擴(kuò)展
- extension UIViewController {
- func viewDidLoadForChangeTitleColor() {
- self.viewDidLoadForChangeTitleColor()
- if self.isKindOfClass(UINavigationController.classForCoder()) {
- self.changeNavigationBarTextColor(self as UINavigationController)
- }
- }
- func changeNavigationBarTextColor(navController: UINavigationController) {
- let nav = navController as UINavigationController
- let dic = NSDictionary(object: UIColor.applicationMainColor(),
- forKey:NSForegroundColorAttributeName)
- nav.navigationBar.titleTextAttributes = dic
- nav.navigationBar.barTintColor = UIColor.applicationSecondColor()
- nav.navigationBar.tintColor = UIColor.applicationMainColor()
- }
- }
2. 編寫用于Hook的工具類
- func swizzlingMethod(clzz: AnyClass, #oldSelector: Selector, #newSelector: Selector) {
- let oldMethod = class_getInstanceMethod(clzz, oldSelector)
- let newMethod = class_getInstanceMethod(clzz, newSelector)
- method_exchangeImplementations(oldMethod, newMethod)
- }
3. 在AppDelegate中調(diào)用
- func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
- swizzlingMethod(UIViewController.self,
- oldSelector: "viewDidLoad",
- newSelector: "viewDidLoadForChangeTitleColor")
- //do others
- return true
- }
4. 原理說明
在程序入口處,通過運(yùn)行時(shí)機(jī)制,動(dòng)態(tài)的替換UIViewController的周期方法viewDidLoad 為我們指定的方法 viewDidLoadForChangeTitleColor 。在viewDidLoadChangeTitleColor 中,需要做兩件事:
· 調(diào)用原來的 viewDidLoad 方法
· 執(zhí)行修改主題色相關(guān)代碼
如何調(diào)用原來的viewDidLoad方法:
在AppDelegate中,通過調(diào)用方法 swizzlingMethod 我們將 viewDidLoad 與viewDidLoadForChangeTitleColor 方法體進(jìn)行了替換,原理如下圖:
從上面的圖可以看出,當(dāng)在 viewDidLoadForChangeTitleColor 中執(zhí)行:
- self.viewDidLoadForChangeTitleColor()
是不會(huì)造成循環(huán)調(diào)用,反而是調(diào)用了我們期望執(zhí)行的 viewDidLoad 方法體。
三、Xib/Storyboard的處理
一些在Xib/Storyboard中設(shè)置的主題色,比如文本顏色,按鈕的高亮顏色等,該如何處理呢,以UILabel為例,建立擴(kuò)展
- extension UILabel {
- var colorString: String {
- set(newValue) {
- switch newValue {
- case "main":
- self.textColor = UIColor.applicationMainColor()
- case "second":
- self.textColor = UIColor.applicationSecondColor()
- case "warning":
- self.textColor = UIColor.applicationWarningColor()
- default:
- self.textColor = UIColor.applicationSecondColor()
- }
- }
- get {
- return self.colorString
- }
- }
- }
在Xib/Storyboard的查檢器中進(jìn)行編輯,如下圖:
四、總結(jié)
1.只有一套主題時(shí),上面的方法可以直接復(fù)制使用,在更換主題時(shí),只需要更換相應(yīng)圖片及修改UIColor的擴(kuò)展類。
2.在有多套主題,用戶可以自由切換主題時(shí),可以按文章中的Hook機(jī)制,對(duì)viewWillAppear 進(jìn)行劫持,也可以輕松實(shí)現(xiàn)主題的改變。
本文鏈接:http://www.cocoachina.com/swift/20141127/10336.html