如何在 iOS 7 中设置 barTintColor 实现类似网易和 Facebook 的 navigationBar 效果
来源:互联网 发布:知乎 复活 编辑:程序博客网 时间:2024/05/15 10:25
先给代码:https://github.com/allenhsu/CRNavigationController
1. 问题的表现
相信很多人在 iOS 7 的适配过程中遇到了类似这样的问题。当你试图通过设置 navigationBar.barTintColor
的时候,你陷入了一个两难的困境,假设你的预期是这样的:
但当 navigationBar.translucent
为 YES
时,你的 navigationBar
看起来可能是这样的:
最简单的方法是妥协地设置 translucent
为 NO
,于是 navigationBar
的背景色看起来与设计稿一致了,但是设计师可能会跟你吐槽这个 navigationBar
一点也不 iOS 7,他希望 navBar 还是可以透出高斯模糊后的背景。
纵观 App Store,网易新闻和 Facebook 似乎比较好地解决了这个问题。
搜集了一些相关资料后自觉找到了不错的解决方案,于是总结成文。
2. iOS 7 中的 barTintColor
《Bar color calculator for iOS7 (UIToolbar and UINavigationBar)》给出了从设计稿色值到 UIColor
的转换和逆转换公式:
假设设计稿中色值为 x
(0-255),转换到 UIColor
用的色值用如下公式:
y = (x - 102) / 0.6
如果取 0-1.0(UIColor
中 RGB 的取值),对应公式:
y = (x - 0.4) / 0.6
反之:
x = 0.6 * y + 0.4
这意味着只设置 barTintColor
,你得到的屏幕上结果的 RGB 值均不会小于 102(0.4),换言之,这样的颜色明度较高,无法覆盖完整的色域。但倘若你的设计稿是一个明度较高的背景色,如灰色 (102, 102, 102),那么只需设置 barTintColor
为纯黑 (0, 0, 0) 就能得到设计稿中所需的背景色,但是大多情况下这个公式无法满足需求。
注:本文所说的屏幕上的结果色值均指与白色底色叠加后的颜色,假设设计稿中色值亦是指白底叠加的情况。
3. 不完美的解决方案
Stackoverflow 上有一个解决方案,作者也在 GitHub 附上了代码。这个方案在我看来并不完美,最大的缺点就是代码中输入的色值并非最终屏幕输出的色值(仍以白底为参考),仍有明显色差。这就意味着如果要实现与设计稿一致的效果,你需要通过不断地调整、取色、对比来找到一个 Magic Value。不过这个方案给出了一个很好的思路,即通过叠加一个半透明的 CALayer
,来改变 navigationBar
的背景色,或者说提高背景色的明度。
4. 色彩叠加
为了减小篇幅,这里把色彩叠加简化为两色叠加,假设 c1
是当前颜色,c2
为覆盖在 c1
上面的颜色,并且透明度(alpha/opacity)为 a
,那么叠加后屏幕上的颜色为 (1 - a) * c1 + a * c2
。
5. 数学问题
剩下的工作就是纯数学问题了,题目是:在 2 中计算所得的颜色上叠加什么颜色和透明度的 Layer,可以得到设计稿中的原色。
假设设计稿色值为 n
,传入 barTintColor
的参数也为 n
(我要求的所设即所得),根据 2 中公式,navigationBar
自带的背景色为:
b1 = 0.6 * n + 0.4
设叠加的 Layer 的背景色为 n2
,透明度为 a
,那么叠加后得到的颜色为:
b2 = (1 - a) * b1 + a * n2 = (1 - a) * (0.6 * n + 0.4) + a * n2
我希望:
b2 = n
即:
(1 - a) * (0.6 * n + 0.4) + a * n2 = n
推导得到:
n2 = 0.4 * n / a + 0. 6 * x + 0.4 - 0.4 / a
为了保证 n2 > 0
,可以得到:
a > (0.4 - 0.4 * n) / (0.6 * n + 0.4)
就是说为了实现部分较深的颜色,a 不得不取较高的值,也就意味着 navBar 的通透度可能会适当降低,例如网易红的例子中,a 大概在 0.78 左右,所以看起来不那么通透。
该不等式的右边是个递减函数,所以取色值 RGB 中的最小值来计算右式最大值从而得到 a
的最小值,该步对应代码中的:
CGFloat minVal = MIN(MIN(red, green), blue);if ([self convertValue:minVal withOpacity:opacity] < 0) { opacity = [self minOpacityForValue:minVal];}
在得到 a
即 opacity
的值后,通过以下代码计算得到叠加的 Layer 的色值:
- (CGFloat)convertValue:(CGFloat)value withOpacity:(CGFloat)opacity{ return 0.4 * value / opacity + 0.6 * value - 0.4 / opacity + 0.4;}
综上,这样计算出来的叠加层的背景色和透明度可以使得叠加后的结果正好与设计稿的色值一致,至此很好地解决了 iOS 7 中 navigationBar
的 barTintColor
的适配问题,该方法同样适用于解决 UIToolBar
和 UITabBar
的背景色的适配。
最后附上 GitHub 地址:https://github.com/allenhsu/CRNavigationController 样例中,Red 为网易红,Blue 为脸书蓝,自行测试效果。
转载自:http://www.imallen.com/blog/2013/10/22/how-to-set-bartintcolor-correctly-in-ios-7.html
- 如何在 iOS 7 中设置 barTintColor 实现类似网易和 Facebook 的 navigationBar 效果
- 如何在 iOS 7 中设置 barTintColor 实现类似网易和 Facebook 的 navigationBar 效果
- 如何在iOS 7中设置barTintColor实现类似网易和 Facebook 的 navigationBar 效果
- iOS 7中设置barTintColor实现类似网易和 Facebook 的 navigationBar 效果
- navigationBar tintColor barTintColor 分别在iOS7和它之前的区别
- 如何在WPF中实现类似Android的ProgressDialog效果
- Viewpager实现类似网易新闻的效果
- iOS tintColor和barTintColor的区别
- iOS中NavigationBar设置
- 在Flex中,如何实现类似html中图片热点链接的效果呢?
- 4 款类似 Facebook/Path 切换效果的 iOS 组件
- iOS中设置NavigationBar的属性
- ios-设置navigationBar和tabBar的样式
- 【iOS开发-23】toolbar工具条和toolbarItems:与navigationBar和navigationItem类似,重点是如何排版工具条的元素
- iOS开发toolbar工具条和toolbarItems:与navigationBar和navigationItem类似,重点是如何排版工具条的元素
- iOS雷达和类似水波纹效果的实现
- 实现类似网易邮箱的顶部工具栏的悬停效果
- 实现类似IOS中滑动按钮效果
- 页面无法打开!
- 在c++类定义时初始化数据成员的方法
- 2013成都国赛反思
- Android 打造自己的个性化应用(三):应用程序的插件化
- Nginx配置文件nginx.conf中文详解
- 如何在 iOS 7 中设置 barTintColor 实现类似网易和 Facebook 的 navigationBar 效果
- android布局方式讲解
- 那些厚黑又细腻的人性社交设计
- 关于文章 A Llook At Gaussian Mixture Reduction Algorithems
- 芒果播放器介绍
- Android 打造自己的个性化应用(四):仿墨迹天气实现-->自定义扩展名的zip格式的皮肤
- 【HBase】Rowkey设计
- Android 打造自己的个性化应用(五):仿墨迹天气实现续--> 使用Ant实现zip/tar的压缩与解压
- VS2005(vs2008,vs2010)使用map文件查找程序崩溃原因