为什么setBarTintColor颜色比原颜色浅

为什么setBarTintColor颜色比原颜色浅

最简单答案: 这是由于半透明模糊引起的  [self.navigationBar setTranslucent:NO];

但是================================================= 但是

转自:i‘m Allen的博客

先给代码: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 的最小值,该步对应代码中的:

  1. CGFloat minVal = MIN(MIN(red, green), blue);
  2. if ([self convertValue:minVal withOpacity:opacity] < 0) {
  3. opacity = [self minOpacityForValue:minVal];
  4. }
  5. 在得到 a 即 opacity 的值后,通过以下代码计算得到叠加的 Layer 的色值:
  6. - (CGFloat)convertValue:(CGFloat)value withOpacity:(CGFloat)opacity
  7. {
  8. return 0.4 * value / opacity + 0.6 * value - 0.4 / opacity + 0.4;
  9. }

综上,这样计算出来的叠加层的背景色和透明度可以使得叠加后的结果正好与设计稿的色值一致,至此很好地解决了 iOS 7 中 navigationBar 的 barTintColor 的适配问题,该方法同样适用于解决 UIToolBar 和 UITabBar 的背景色的适配。

最后附上 GitHub 地址:https://github.com/allenhsu/CRNavigationController 样例中,Red 为网易红,Blue 为脸书蓝,自行测试效果。

时间: 2024-12-11 17:49:50

为什么setBarTintColor颜色比原颜色浅的相关文章

CSS颜色表示法和颜色表

颜色表示法 color name:颜色的名称: color:red:   直接用英文意思来写,但是数量有限,不支持透明颜色   十六进制方式: color:#191d11:所有#开头的都是16进制   rgb(十进制,十进制,十进制)表示方法: 每个值的取值范围是0~255,一共256个   rgba(十进制,十进制,十进制,小数0~1): 最后的a是alpha通道,表示透明度,取值范围在0~1   hsl(色相,饱和度,亮度): h:色相,表示范围0~360,如下如色环 s:饱和度,取值范围是

8.超链接

<html> <head> <title>超链接</title> </head> <body> <a href="">想看美女吗?</a><br/> <a>第一章</a><br/> <a href="#2">第二章</a><br/> <a href="#3">

6st 关于颜色使用方法和颜色表

CSS中表示颜色有三种方法:     1.使用十六进制值设置的颜色  <对光源进行设置的最低值可以是 0(十六进制 00).最高值是 255(十六进制 FF).十六进制值使用三个双位数来编写,并以 # 符号开头.>     2.使用 rgb 值(红绿蓝颜色值)设置的颜色.RGB 颜色值是这样规定的:rgb(red, green, blue).每个参数 (red.green 以及 blue) 定义颜色的强度,可以是介于 0 与 255 之间的整数,或者是百分比值(从 0% 到 100%).rgb

js 判断颜色是否为深色 阀值

//获取RGB值 颜色深用白色 颜色浅则用黑色 var RgbValue = this.style.backgroundColor.replace("rgb(", "").replace(")", ""); var RgbValueArry = RgbValue.split(","); var $grayLevel = RgbValueArry[0] * 0.299 + RgbValueArry[1] *

linux终端c语言改变输出字体颜色

Linux下C改变输出字体颜色 例: #include int main() { printf("\033[31mThis is RED.\n\033[0m"); return 0; } 31m代表字体为红色,0m代表关闭所有属性. 常用的ANSI控制码如下(有些不支持): \033[0m 关闭所有属性 \033[1m 高亮 \033[2m 亮度减半 \033[3m 斜体 \033[4m 下划线 \033[5m 闪烁 \033[6m 快闪 \033[7m 反显 \033[8m 消隐 \

PixelFormat 图像颜色的数据格式

PixelFormat: (指定图像中每个像素的颜色数据的格式) Delphi                                        微软                                  说明 PixelAlpha                                Alpha                        像素数据包含没有进行过自左乘的 alpha 值. PixelCanonical                     

【转】使用blend改变图片颜色

最近对Core Animation和Core Graphics的内容东西比较感兴趣,自己之前也在这块相对薄弱,趁此机会也想补习一下这块的内容,所以之后几篇可能都会是对CA和CG学习的记录的文章. 在应用里一个很常见的需求是主题变换:同样的图标,同样的素材,但是需要按照用户喜爱变为不同的颜色.在iOS5和6的SDK里部分标准控件引入了tintColor,来满足个性化界面的需求,但是Apple在这方面还远远做的不够.一是现在用默认控件根本难以做出界面优秀的应用,二是tintColor所覆盖的并不够全

c# color 颜色代码

这篇文章来来源于C# Color Table,这里是我翻译的中文版本,其中已经加上了我的一些理解和注释.翻译这篇文章的原因是我在写C#程序的时候发现,C#自带的颜色种类极多(详见下表),如果没有直观的对照关系的话,很难从那么多的名字中挑选出中意的颜色. 以下的颜色代码取自HTML规范,这些颜色的名称对应于KnownColor的属性.比如,你可以用以下代码来创建一个Color对象: Color c = Color.FromKnownColor(KnownColor.colorname); 所有的c

一串首尾相连的珠子(m个),有N种颜色(N&lt;=10),使得最短的字符串包含全部颜色

思路:先从index=0处搜索,每检查一颗珠子,响应的颜色数量+1,如果是新的颜色则总颜色数+1. 当颜色总数为n时,找到第一个满足条件的连续序列. 1>从该序列起始处搜索,若搜索处的颜色数量不为1,则表明该串还有别的珠子有该颜色,继续往前搜索并更新该序列,起始索引位置+1. 若搜索处颜色数量为1,停止搜索. 2>比较最佳序列长与当前序列长,更新最佳序列.记录当前序列起始位置. 从第一个满足条件的序列继续index++,并检查1,2条件. 如果不是首尾相连的: #include <ios