iOS开发——完整项目实战Swift篇&百思不得姐Swift版总结(二)

百思不得姐Swift版总结(二)

tabBar和NavBar配色方案

一、常规主题色使用点

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

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

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

步骤一:变化分离

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

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

 1 extension UIColor {
 2
 3     //主题色
 4     class func applicationMainColor() -> UIColor {
 5         return UIColor(red: 238/255, green: 64/255, blue: 86/255, alpha:1)
 6     }
 7
 8     //第二主题色
 9     class func applicationSecondColor() -> UIColor {
10         return UIColor.lightGrayColor()
11     }
12
13     //警告颜色
14     class func applicationWarningColor() -> UIColor {
15         return UIColor(red: 0.1, green: 1, blue: 0, alpha: 1)
16     }
17
18     //链接颜色
19     class func applicationLinkColor() -> UIColor {
20         return UIColor(red: 59/255, green: 89/255, blue: 152/255, alpha:1)
21     }
22
23 }

二、TabBar主题色设置

很多应用中,默认情况下都使用了TabBar控件,但是TabBar主题色等设置根据使用情况的不同,设置起来也不一样。代码创建比较灵活,更改主题色比较容易。而使用了Xib/Storyboard也是有办法做统一处理的,如下,迭代更改TabBar默认字体颜色

1 func configTabBar() {
2         let items = self.tabBar.items
3         for item in items as [UITabBarItem] {
4             let dic = NSDictionary(object: UIColor.applicationMainColor(),
5              forKey:   NSForegroundColorAttributeName)
6             item.setTitleTextAttributes(dic,
7              forState: UIControlState.Selected)
8         }
9     }

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

1 let imageNormal = UIImage(contentsOfFile: "imageNormal")?.
2 imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
3 let imageSelected = UIImage(contentsOfFile: "imageSelected")
4 let tabBarItem = UITabBarItem(title: "title",
5          image: imageNormal,
6          selectedImage: imageSelected)

三、一劳永逸,利用Hook原理通设NavigationBar颜色

IOS应用中,NavigationBar十分常用,它的使用主要包括以下两个场景

  • 1.代码直接构建
  • 2.Xib/Storyboard构建


果是纯代码构建的时候,比较简单,直接使用UIColor的扩展来设置颜色。实际项目中,有些界面是通过Xib/Storyboard来创建的,有些是代
码写的,但这也难不到大家,使用继承。创建一个继承自UINavigationController的子类,通过这个子类来统一设置主题色。然后告诉项目
中的所有人,强制使用UINavigationController子类,包括Xib/Storyboard等。问题是旧项目怎么办,这种强制要求可以工
作,有没有一个更好的办法,让所有人正常使用UINavigationController,而在神不知鬼不觉的情况下,通设所有
NavigationBar呢? 先上代码,再解释

1.创建一个UIViewController的扩展

 1 extension UIViewController {
 2     func viewDidLoadForChangeTitleColor() {
 3         self.viewDidLoadForChangeTitleColor()
 4         if self.isKindOfClass(UINavigationController.classForCoder()) {
 5            self.changeNavigationBarTextColor(self as UINavigationController)
 6         }
 7     }
 8
 9     func changeNavigationBarTextColor(navController: UINavigationController) {
10         let nav = navController as UINavigationController
11         let dic = NSDictionary(object: UIColor.applicationMainColor(),
12          forKey:NSForegroundColorAttributeName)
13         nav.navigationBar.titleTextAttributes = dic
14         nav.navigationBar.barTintColor = UIColor.applicationSecondColor()
15         nav.navigationBar.tintColor = UIColor.applicationMainColor()
16
17     }
18
19 }

2.编写用于Hook的工具类

1 func swizzlingMethod(clzz: AnyClass, #oldSelector: Selector, #newSelector: Selector) {
2     let oldMethod = class_getInstanceMethod(clzz, oldSelector)
3     let newMethod = class_getInstanceMethod(clzz, newSelector)
4     method_exchangeImplementations(oldMethod, newMethod)
5 }

3.在AppDelegate中调用

1   func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
2         swizzlingMethod(UIViewController.self,
3         oldSelector: "viewDidLoad",
4         newSelector: "viewDidLoadForChangeTitleColor")
5   //do others
6         return true
7     }

4.原理说明

在程序入口处,通过运行时机制,动态的替换UIViewController的周期方法viewDidLoad为我们指定的方法viewDidLoadForChangeTitleColor。在viewDidLoadChangeTitleColor中,需要做两件事:

调用原来的viewDidLoad方法
执行修改主题色相关代码
1.如何调用原来的viewDidLoad方法

在AppDelegate中,通过调用方法swizzlingMethod我们将viewDidLoad与viewDidLoadForChangeTitleColor方法体进行了替换,原理如下图:

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

  • self.viewDidLoadForChangeTitleColor()

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

四、Xib/Storyboard的处理

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

 1 extension UILabel {
 2     var colorString: String {
 3         set(newValue) {
 4             switch newValue {
 5             case "main":
 6                 self.textColor = UIColor.applicationMainColor()
 7             case "second":
 8                 self.textColor = UIColor.applicationSecondColor()
 9             case "warning":
10                 self.textColor = UIColor.applicationWarningColor()
11             default:
12                 self.textColor = UIColor.applicationSecondColor()
13             }
14         }
15         get {
16             return self.colorString
17         }
18     }
19 }

在Xib/Storyboard的查检器中进行编辑,如下图:

4.总结

  • 1.只有一套主题时,上面的方法可以直接复制使用,在更换主题时,只需要更换相应图片及修改UIColor的扩展类
  • 2.在有多套主题,用户可以自由切换主题时,可以按文章中的Hook机制,对viewWillAppear进行劫持,也可以轻松实现主题的改变
时间: 2024-10-19 16:33:13

iOS开发——完整项目实战Swift篇&百思不得姐Swift版总结(二)的相关文章

iOS开发——完整项目实战OC篇&百思不得姐第四天

iOS开发——完整项目实战OC篇&百思不得姐第四天 上午 一:自定义按钮使用九宫格布局 二:控件不能点击 三:获取用户点击了那个按钮 四:调整按钮内部控件的位置:主流->上下 五:不能直接使用self.navigationController中或者View中获取导航控制器 方法一: 方法二: 六:布局取整 1 // 总行数 2 3 // NSUInteger rows = sqaures.count / maxCols; 4 5 // if (sqaures.count % maxCols)

iOS开发——完整项目实战OC篇&百思不得姐第一天

百思不得姐第一天 做好准备,我们要开干了...... 先声明,我不过给出过多的代码实现,除非是一些重要的(开发中常用的),或者是比较难理解的. 主要介绍一些思路和简单功能的总结,还有一些遇到的错误及处理! 上午 一:修改项目名称(之前是Buble DisplayName) 二:删除(没有launchXIB的时候会显示界面错误),再iOS8以后屏幕的显示跟启动图片有关 需要删除对应,并且设置launchImages 或者我们可以自己在images.xcasesets中新建我们的launchImag

iOS开发——完整项目实战OC篇&百思不得姐第五天

百思不得姐第五天 上午 一:蒙板 tabBarController:addsubViews Window:rootViewController Modal:presentViewController(rootViewController) 二:显示界面不是想要的效果 由于是使用Xib所以默认在ViewDidLoad中的frame是对应Xib的frame:(600,600) 我们如果要实现布局应该在-viewDidLayoutSubViews实现 但是如果真的要在ViewDidLoad里面实现我们

iOS开发——完整项目实战OC篇&百思不得姐第十一天

百思不得姐第十一天 一:模型中没有ID这个属性 为模型增加一个属性ID,设置名字替换 /** id */ @property (nonatomic, copy) NSString *ID; 替换: + (NSDictionary *)replacedKeyFromPropertyName {     return @{@"ID" : @"id"}; } 二:错误的将数组当作字典来用(其实就是没有数据,比如刷新数据已经没有了,或者直接就是0) 通过堆栈定位错误 最后一

iOS开发——完整项目实战OC篇&百思不得姐第八天

百思不得姐第八天 上午 一:监听ScrollView停止两种方法 代码实现滚动的时候:必须要有动画 拖拽实现滚动的时候 二:ScrollView中,对应的X/Y宽高都相等的时候frmae就等一bounds 三:判断View是否在对应的View上面 1:判断父控件 2:看Window是否有值 3:是否创建加载 四:autormaticllyAdjustScrollViewInsets 五:内边距设置 1:tableView尺寸还是屏幕的尺寸(高度) 2:不被导航栏河tabBar挡住(用户能看齐所有

iOS开发——完整项目实战OC篇&百思不得姐第三天

百思不得姐第三天 上午 错误:键盘处理 设置cell的分割线 方法一:添加一个View再上面 方法二:修改对应的Frame 拦截系统frame的设置,根据需求修改对应的值 不管别人传什么进来原值都不变,使用我们默认的值 优化 控制器挂掉取消 AFN内部实现 直接终止请求 暂停请求 取消请求总结 AFN返回码 debug不能全为小写 两者不同,下面的带IBOutlet的内部会隐士的强引用着他 所以调用方式是先打印后面的,就是说走完第一行之后并且没有销毁,等}走完之后就销毁 下午 设置圆形图片的简单

iOS开发——完整项目实战OC篇&百思不得姐第二天

百思不得姐第二天 上午 一调用父类先后顺序问题 二:手势滑动 解决问题 1 // 什么时候调用:每次触发手势之前都会询问下代理,是否触发. 2 // 作用:拦截手势触发 3 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer 4 { 5 // 注意:只有非根控制器才有滑动返回功能,根控制器没有. 6 // 判断导航控制器是否只有一个子控制器,如果只有一个子控制器,肯定是根控制器 7 if (s

iOS开发——完整项目实战OC篇&百思不得姐第十天

百思不得姐第十天 一:设置时间的显示 显示如下 二:MJExtension类型(名字)的指定——映射 1.在模型实中 2.字典转模型中 三:常见问题 问题1:多个对一个 有时候可能会有多个属性对应一个名字的时候我们就需要使用的到数组 问题2:子模型中的名字 问题3:返回复杂的数据(比如在一个字典里面还有一个字典再在里面有一个url数组) 统一处理 四:模型中嵌套模型:数组中存放模型(模型里面有数组数组里面又装着模型) 或者在代理或在一个独立的文件中的load方法中 五:没有注释 没有参与编译 @

iOS开发——完整项目实战OC篇&百思不得姐第六天

百思不得姐第六天 上午 一:使用Xib加载View 一般我们直接在分类里面,因为Xib加载的代码都是一样 二:键盘的两个常见属性 inoutAccessoryView inputView 三:切换系统和自定义键盘的简单使用方式,是不是很变态 根据使用的键盘判断类型并且切换 四:使用动画的方式,其实就是设置切换的时间就可以了 五:特殊需求,直接总定义并且添加View(不使用inoutAccessoryView) 使用通知实现工具条跟着键盘的移动:(上移键盘的高度) 1:改变Y值,上下改变Y值->使

iOS开发——完整项目实战OC篇&百思不得姐第七天

百思不得姐第七天 上午 一:传值方式 谁传值(主动方):谁发通知. 谁传值(主动方):创建Blcok(判断). 谁传值(主动方):创建协议,代理方法. 详细请看: http://www.cnblogs.com/iCocos/p/4659878.html http://www.cnblogs.com/iCocos/p/4550169.html 二:按钮中的文字获取 方法一: 方法二: 将数组的所有path对应的属性取出来,放到一个数组厘面去 三:装逼试判断:三木运算 四:数组不能一边遍历一边删除