Swift主題色頂級解決方案
Swift應用程序的主題色解決方案,主要包括TabBar、NavigationBar、其它設置等,讓程序更改主題色更加容易
一、常規主題色使用點
應用在發布前都會對其主題色進行設置,以統一應用的風格(可能有多套主題)。在主題色設置上有幾個方面,如下:
1.TabBar部分,設置圖片高亮、文本高度顏色
2.NavigationBar部分,設置導航欄顏色及字體顏色
3.應用標簽等,設置字體的顏色
4.應用圖片主題色
主題色的設置點,大體從上面四個方面著手,圖片的主題色我們可通過圖片更換的方式進行處理。而通過代碼來處理的`1-3`條,有著不同的處理方法。大家常規處理方法如下:
步驟一:變化分離
1.利用Swift擴展語法擴展UIColor,將應用主題色在擴展中統一處理(適合單一主題色)
2.將主題色的配置寫入文件中,由相應邏輯進行解析。此方法將主題色邏輯封裝成主題色管理類(適合多套主題)
步驟二:離散使用上步封裝的類
1.在任何使用主題色的地方,使用擴展中的UIColor方法來設置,一般包括背景色,文字顏色等
這里給出UIColor的擴展
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主題色設置
很多應用中,默認情況下都使用了TabBar控件,但是TabBar主題色等設置根據使用情況的不同,設置起來也不一樣。代碼創建比較靈活,更改主題色比較容易。而使用了Xib/Storyboard也是有辦法做統一處理的,如下,迭代更改TabBar默認字體顏色
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) } }
設置TabBar圖片及文字默認選中顏色
self.tabBar.selectedImageTintColor = UIColor.applicationMainColor()
Tips注意事項
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.
在一些情況,正常狀態為白色圖片時,真機測試時,白色圖片會出現偏色(顯示結果為灰色),這是因為系統默認著色導致的,在創建UITabBarItem時,可通過使用UIImageRenderingModeAlwaysOriginal避免。示例代碼如下:
let imageNormal = UIImage(contentsOfFile: "imageNormal")?. imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal) let imageSelected = UIImage(contentsOfFile: "imageSelected") let tabBarItem = UITabBarItem(title: "title", image: imageNormal, selectedImage: imageSelected)
三、一勞永逸,利用Hook原理通設NavigationBar顏色
IOS應用中,NavigationBar十分常用,它的使用主要包括以下兩個場景
1.代碼直接構建
2.Xib/Storyboard構建
如果是純代碼構建的時候,比較簡單,直接使用UIColor的擴展來設置顏色。實際項目中,有些界面是通過Xib/Storyboard來創建的,有些是代碼寫的,但這也難不到大家,使用繼承。創建一個繼承自UINavigationController的子類,通過這個子類來統一設置主題色。然后告訴項目中的所有人,強制使用UINavigationController子類,包括Xib/Storyboard等。問題是舊項目怎么辦,這種強制要求可以工作,有沒有一個更好的辦法,讓所有人正常使用UINavigationController,而在神不知鬼不覺的情況下,通設所有NavigationBar呢?
先上代碼,再解釋
1.創建一個UIViewController的擴展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中調用
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { swizzlingMethod(UIViewController.self, oldSelector: "viewDidLoad", newSelector: "viewDidLoadForChangeTitleColor") //do others return true }
4.原理說明
在程序入口處,通過運行時機制,動態的替換UIViewController的周期方法viewDidLoad為我們指定的方法viewDidLoadForChangeTitleColor。在viewDidLoadChangeTitleColor中,需要做兩件事:
* 調用原來的viewDidLoad方法
* 執行修改主題色相關代碼
1.如何調用原來的viewDidLoad方法
在AppDelegate中,通過調用方法`swizzlingMethod`我們將viewDidLoad與viewDidLoadForChangeTitleColor方法體進行了替換,原理如下圖:
從上面的圖可以看出,當在viewDidLoadForChangeTitleColor中執行:
self.viewDidLoadForChangeTitleColor()
是不會造成循環調用,反而是調用了我們期望執行的viewDidLoad方法體。
三、Xib/Storyboard的處理
一些在Xib/Storyboard中設置的主題色,比如文本顏色,按鈕的高亮顏色等,該如何處理呢,以UILabel為例,建立擴展
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的查檢器中進行編輯,如下圖:
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 } } }
4.總結
1.只有一套主題時,上面的方法可以直接復制使用,在更換主題時,只需要更換相應圖片及修改UIColor的擴展類
2.在有多套主題,用戶可以自由切換主題時,可以按文章中的Hook機制,對viewWillAppear進行劫持,也可以輕松實現主題的改變。
來自:http://my.oschina.net/taptale/blog/349343