一、常规主题色使用点

应用在发布前都会对其主题色进行设置,以统一应用的风格(可能有多套主题)。在主题色设置上有几个方面,如下:

1.TabBar部分,设置图片高亮、文本高度颜色
2.NavigationBar部分,设置导航栏颜色及字体颜色
3.应用标签等,设置字体的颜色
4.应用图片主题色

主题色的设置点,大体从上面四个方面着手,图片的主题色我们可通过图片更换的方式进行处理。而通过代码来处理的1-3条,有着不同的处理方法。大家常规处理方法如下:

步骤一:变化分离

1.利用Swift扩展语法扩展UIColor,将应用主题色在扩展中统一处理(适合单一主题色)
2.将主题色的配置写入文件中,由相应逻辑进行解析。此方法将主题色逻辑封装成主题色管理类(适合多套主题)

步骤二:离散使用上步封装的类

1.在任何使用主题色的地方,使用扩展中的UIColor方法来设置,一般包括背景色,文字颜色等

这里给出UIColor的扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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默认字体颜色

1
2
3
4
5
6
7
8
9
 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图片及文字默认选中颜色

1
    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避免。示例代码如下:

1
2
3
4
5
6
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的扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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的工具类

1
2
3
4
5
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中调用

1
2
3
4
5
6
7
  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我们将viewDidLoadviewDidLoadForChangeTitleColor方法体进行了替换,原理如下图:

从上面的图可以看出,当在viewDidLoadForChangeTitleColor中执行:

1
self.viewDidLoadForChangeTitleColor()

是不会造成循环调用,反而是调用了我们期望执行的viewDidLoad方法体。

三、Xib/Storyboard的处理

一些在Xib/Storyboard中设置的主题色,比如文本颜色,按钮的高亮颜色等,该如何处理呢,以UILabel为例,建立扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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的查检器中进行编辑,如下图:

4.总结

1.只有一套主题时,上面的方法可以直接复制使用,在更换主题时,只需要更换相应图片及修改UIColor的扩展类

2.在有多套主题,用户可以自由切换主题时,可以按文章中的Hook机制,对viewWillAppear进行劫持,也可以轻松实现主题的改变

Posted by 一叶 Nov 27th, 2014 experience

原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0

Swift主题色顶级解决方案一的更多相关文章

  1. Swift主题色顶级解决方案

    一.常规主题色使用点 应用在发布前都会对主题色进行设置,以统一应用的风格(可能有多套主题).在主题色设置上有几个方面,如下: 1. TabBar部分,设置图片高亮.文本高度颜色2. Navigatio ...

  2. antd 主题色

    如果是自己配置的reac项目,而非官方推荐的creat-react-app或者dva-cli等阿里自己开发的脚手架去引入antd,会有两个问题 第一,用babel-plugin-import设置sty ...

  3. Swift - UITableViewCell倒计时重用解决方案

    Swift - UITableViewCell倒计时重用解决方案 效果 源码 https://github.com/YouXianMing/Swift-Animations // // CountDo ...

  4. element-ui更换主题色

    1.cd到你的项目文件目录下,npm i element-theme -g 2.npm i element-theme-default -D 3.et -i 执行后当前目录会有一个 element-v ...

  5. element ui主题色跟换

    node_modules\ element ui\ lib\ theme-dafault  下载的主题色替换掉改文件... ================== 但是会出现  搜索框iocon 样式换 ...

  6. 在webpack自定义配置antd的按需加载和修改主题色

    最近使用antd来做react项目的UI.从antd官网上,在使用create-react-app脚手架搭建项目时步骤如下: (1)添加模块 react-app-rewired, babel-plug ...

  7. WP8.1 中获取背景色和主题色

    背景色: Application.Current.RequestedTheme 返回的值是一个枚举,Light 或者 Dark. 主题色: public static Color GetPhoneAc ...

  8. MahApps.Metro扁平化UI控件库(可修改主题色等)

    一.名词解释 使用MahApps.Metro扁平化UI控件库,可以使界面呈现更加美观.本文将总结MahApps.Metro的使用方法,及如何自定义修改其主题颜色等. 详细内容可参考官网:https:/ ...

  9. vue项目中引入element-ui时,如何更改主题色

    在我们做项目时,我们经常会遇到切换主题色的功能,下面我们就来说一下通过颜色选择器我们就能改变项目的主题颜色 代码如下: 颜色选择器所在组件: top-theme.vue内容如下: <templa ...

随机推荐

  1. iOS 10中如何搭建一个语音转文字框架

    在2016WWDC大会上,Apple公司介绍了一个很好的语音识别的API,那就是Speech framework.事实上,这个Speech Kit就是Siri用来做语音识别的框架.如今已经有一些可用的 ...

  2. Dos关闭进程命令

    netstat -ao 查找占用端口的进程 taskkikk /pid 端口pid  /f

  3. Hadoop学习笔记(4)hadoop集群模式安装

    具体的过程参见伪分布模式的安装,集群模式的安装和伪分布模式的安装基本一样,只有细微的差别,写在下面: 修改masers和slavers文件: 在hadoop/conf文件夹中的配置文件中有两个文件ma ...

  4. html 表头固定

    <div style="width: 100%; min-width: 300px; padding-right: 10px;"> <table style=&q ...

  5. 利用console控制台调试php代码

    /** * 控制台输出 * @param $var * @param string $level */ public function console($var,$level = 'debug') { ...

  6. python自学笔记(二)python基本数据类型之字符串处理

    一.数据类型的组成分3部分:身份.类型.值 身份:id方法来看它的唯一标识符,内存地址靠这个查看 类型:type方法查看 值:数据项 二.常用基本数据类型 int 整型 boolean 布尔型 str ...

  7. Java解析器

    http://www.infoq.com/cn/articles/HIgh-Performance-Parsers-in-Java-V2?utm_source=infoq&utm_medium ...

  8. 一个int 数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。

    一个int数组, 比如 array[],里面数据无任何限制,要求求出 所有这样的数array[i],其左边的数都小于等于它,右边的数都大于等于它.能否只用一个额外数组和少量其它空间实现. 分析:这题很 ...

  9. 使用 IIS Manager 对 Windows Azure 网站进行远程管理

     最近,我们为客户新增了使用 Windows自带的 IIS管理控制台管理 Azure网站的功能.IIS Manager支持 HTTP over SSL,提供到您的 Windows Azure 网站 ...

  10. 基于Visual C++2013拆解世界五百强面试题--题10-找出N个数种最大的K个数

    有一亿个整数,请找出最大的 1000 个,要求时间越短越好, 空间占用越好越好. 如果不考虑时间效率,很容易想到解决方法,我们只需存储前一千个数, 然后依次读入后面的数和这一千个数组比较,替换其中比较 ...