iOS的毛玻璃效果

系统控件

苹果在iOS7很多系统界面中都使用了毛玻璃效果,增加了界面的美观性,具有该效果的控件有

  • UINavigationBar
  • UIToolBar
  • UIToolbar

这些控件的毛玻璃效果是基于同一套高斯模糊算法,为了问题的简单化,下文只对UINavigationBar进行分析。

相信很多人遇到过如下的问题:

  • navigationBar.translucent为NO时,无高斯模糊,生硬
  • navigationBar.translucent为YES时,有高斯模糊,颜色会变浅

预计效果


iOS的毛玻璃效果_第1张图片
Paste_Image.png

实际效果


iOS的毛玻璃效果_第2张图片
Paste_Image.png

根本原因是系统所用的高斯模糊算法会对色值进行一个转化,从设置值到表现值的转化关系如下

y = (x - 102) / 0.6; // 设置值y的范围[0, 255]
y = (x - 0.4) / 0.6; // 设置值y的范围[0, 1.0]

这样导致表现值无法覆盖完整的色域

x = 0.6y + 102; // 表现值x均>=102
x = 0.6y + 0.4; // 表现值x均>=0.4

解决方案有两种

方案一:盖一个layer到navigationBar上,色彩叠加
方案二:盖一个layer到navigationBar上,直接显示

色彩叠加方案

layer1:navigationBar的设置值y1,表现值l1,满足l1 = 0.6y1 + 0.4
layer2:stickView的透明度a,表现值l2,设置值待求
叠加后色值: (1 - a) * l1 + a * l2 = (1 - a) * (0.6 * y1 + 0.4) + a * l2
所设即所得就是叠加后色值==y1,也就是 (1 - a) * (0.6 * y1 + 0.4) + a * l2 = y1
可推导出:l2 = 0.4 * y1 / a + 0. 6 * y1 + 0.4 - 0.4 / a
为了保证 l2 > 0
可推导出:a > (0.4 - 0.4 * y1) / (0.6 * y1 + 0.4)

相关代码

- (CGFloat)minOpacityForValue:(CGFloat)value
{
    return (0.4 - 0.4 * value) / (0.6 * value + 0.4);
}

- (CGFloat)convertValue:(CGFloat)value withOpacity:(CGFloat)opacity
{
    return 0.4 * value / opacity + 0.6 * value - 0.4 / opacity + 0.4;
}

直接显示方法

自定义控件

苹果在iOS8后新增了UIBlurEffect类和UIVisualEffectView类,可以更简单高效地实现毛玻璃效果。

    UIImageView * imageView = [[UIImageView alloc] init];
    UIBlurEffect * blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
    UIVisualEffectView * effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    effectView.frame = imageView.bounds;
    effectView.alpha = 0.5f;
    [imageView addSubview:effectView];

参考资料

你可能感兴趣的:(iOS的毛玻璃效果)