UIView并没想的那么简单 - tintColor揭秘

这篇文章针对新手向 iOS 玩家, 请老鸟自行飘过_
目前很多 iOS 新手都是通过拖拖控件, 搞搞 UI 这种方式入门的, 毕竟直观易懂, What You See Is What You Get 的方式也很容易接受, 降低入门门槛. 可凡事都要辩证地看, 正是这种相对容易的学习方式会令你忽略很多东西.
闲话不多啥, 直接进入主题!


首先让我们回到最初的起点, 回到那最单纯的开始. 在一个新建的 Single View Application 的空白 Main.storyboard 中拖入一个 UIButton, 好了, 大功告成! 成果如下:


UIView并没想的那么简单 - tintColor揭秘_第1张图片

你确定这不是在逗我? 这有什么好说的!!!
那么问题来了! 为什么"Button"这几个字是蓝色的?
你可能会说, 这是系统设定的, 跟我有什么关系? Alright! Alright! 现在来点儿更有趣的, 我们为这个 Button 加一个 image, 注意, 不是 backgroundImage.
这个要加载的 image 原来长成这个样子, 见下图:


UIView并没想的那么简单 - tintColor揭秘_第2张图片

如果显示器不偏色的话, 你看到的应该是一张黑色的图片. 可是, 把它设置为 Button 的 image 后, 居然变成这个样子了:
UIView并没想的那么简单 - tintColor揭秘_第3张图片

你可能会说, 我的明明是这样的啊:


UIView并没想的那么简单 - tintColor揭秘_第4张图片

朋友, 当心! 通过 storyboard 为 Button 设置 image 属性后, 这个 Button 的 Type 属性会变为 Custom, 把它改回 System 就变成蓝色的了.
细心的你可能已经发现了, 这个 Button 的 Type 至关重要啊, 直接影响 Button 会长成什么样子. 没错, Type 为 System 时, Button 就会受某些系统参数的影响, 那到底是系统的什么东西在影响着 Button 的样子呢?

我们的主角终于要正式登场啦! 这个会对 Button 的样子产生影响的所谓的"系统的东西"就是 tintColor, 这是一个 UIColor 类型的属性. 这个词儿怎么翻译? 算了, 还是不要纠结翻译的问题了, 就直接称呼它的英文名吧...
先来一个粗略的认识, 大家可以认为系统默认的 tintColor 就是蓝色的, 于是乎整个 App 中采用 System 类型的 Button 就都变蓝了. 其实, 受其影响的还不只 UIButton, 回想一下, 你创建的 navagation controller 和 tabbar controller, 是不是导航栏里的东西默认都是蓝色的? 还有 slider 在滑动时露出的部分也是蓝色的? 还有一些其他的控件也受其影响, 这里不再赘述了.
看来, 我们终于逮到了这个所谓的"系统级别"的元凶! 那问题来了, 凭什么我就一定要用系统设定好的蓝色? 我就是要改成别的颜色, 怎么办? 显然对每个控件都进行自定义是不现实的. 没错, Xcode 确实提供了毕其功于一役的利器. 如果你是用 storyboard 创建界面的, 那么只要在入口控制器的 File Inspector 中修改一下 Global Tint 即可, 见下图:


UIView并没想的那么简单 - tintColor揭秘_第5张图片

修改一下试试吧, 是不是你的所有控件都变色了? 就这么简单!


问题又来了, 如果不通过 storyboard 的方式来加载界面, 而是通过纯代码的方式来实现界面的要怎么办? 至此, 终于要开始探究 tintColor 最有趣的部分了!
不知道大家有没有仔细查看头文件, tintColor 是 iOS7.0 引入的一个 UIView 的属性. 再来强调一下, tintColor 是 UIView 的属性!!! 虽然没有说三遍, 但这一点非常重要! 这就意味着, 所有的 UI 控件都有 tintColor 这个属性! 可是我们平时也没注意到这个东西啊, 这是怎么回事儿?
其实, tintColor 这个东西非常神奇, 它具有继承, 重写, 传播的特点.

  • 继承
    只要一个 UIView 的 subview 没有明确指定 tintColor, 那么这个 view 的 tintColor 就会被它的 subview 所继承! 在一个 App 中, 最顶层的 view 就是 window, 因此, 只要修改 window 的 tintColor, 那么所有 view 的 tintColor 就都会跟着改变.(这种说法其实并不严谨, 请耐心继续看下去_)
  • 重写
    如果明确指定了某个 view 的 tintColor, 那么这个 view 就不会继承其 superview 的 tintColor, 而且自此, 这个 view 的 subview 的 tintColor 会发生改变.
  • 传播
    一个 view 的 tintColor 的改变会立即向下传播, 影响其所有的 subview, 直至它的一个 subview 明确指定了 tintColor 为止.

感觉上述三点读起来像绕口令有没有? 不要担心, 通过下述例子, 希望可以帮你理清脉络.
首先在一个 ViewController 中加入三个普通的 UIView, 并且一一构成父子关系, 即 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揭秘_第6张图片

此时, 由于三个 UIView 的 tintColor 都没有明确指定, 那么它们的 tintColor 都会继承自最顶层的 view - window - 即蓝色. 好了, 既然三个 view 和三个 Button 都是 window 的 subview, 那么它们的 tintColor 就一并都变为了蓝色.
此时, 只要改变一下 window 的 tintColor, 效果就完全不一样了, 见下图:


UIView并没想的那么简单 - tintColor揭秘_第7张图片

怎么样? 这与在 storyboard 中修改 Global Tint 的效果是相同的. 同时, 这也证明了 tintColor 的改变是能够向下传播的. 想要达到这种效果还能怎么实现? 没错, 不需要修改 window 的 tintColor, 修改 First View 的 tintColor 也同样奏效! 因为 tintColor 的改变是向下传播的, 重要的事情说 N 遍!!
此时, 如果我们明确指定了 Second View 的 tintColor 会如何? 看看实际效果是不是与你设想的相同:
UIView并没想的那么简单 - tintColor揭秘_第8张图片

可以看到, 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, 那么你就会看到一个新的世界:


UIView并没想的那么简单 - tintColor揭秘_第9张图片

怎么样? 差不多理清 tintColor 的继承, 重写以及传播是怎么回事儿了吧.
总结一下就是: 对一个 view 来说, 只要它的 tintColor 没有明确指定, 那么它就会采用其 superview 的 tintColor. 一旦这个 view 的 tintColor 改变了, 这种改变就会一直向其 subview 传播, 直至某个 subview 明确指定了 tintColor 为止.
此外, 在某个 view 的 tintColor 发生改变时, 这个 view 以及它所有受影响的 subview 都会调用 tintColorDidChange 方法, 所以有什么自定义操作, 都可以在这个方法中进行.
好了, 希望大家利用 tintColor 的特点来打造五彩斑斓的界面吧!

你可能感兴趣的:(UIView并没想的那么简单 - tintColor揭秘)