最近感受本身老是学习网络相关的, 有点"疲劳"了. 因此今天换个口味, 试着翻译下国外大神的博客. 有很差的地方还请赐教!ios
先让咱们一块儿看看苹果是如何在系统中使用的. 数据库
其中, 控制中心是一个值得关注的示例. 模糊背景为控制中心的操做提供环境 - 虽然控制中心不属于某一个APP, 但它却显示在这些活动APP的上方.swift
通知中心也使用了该效果, 可是, 这里不是让整个背景都模糊了, 每个extension或通知都有本身模糊的背景. 这不只看上去漂亮, 并且使每个元素都很显眼.xcode
那么如何在本身的APP中再现这些效果呢? 没错, 就是使用iOS内建的UIVisualEffectView
! 该篇, 你将学到关于使用"模糊效果"的一切, 以使你的APP更出众.bash
如何优雅,高效的使用须要必定的技巧. 这里会了解到"模糊效果"使用到的常规算法.网络
全部的模糊效果都始于一张图片. 为了实现该效果, 你须要对图片的每个像素应用模糊算法(blurring algorithm)
, 这样能够获得一个均匀的带有模糊效果的副本. 不一样种类的模糊算法有很大差别, 而且错综复杂, 这里咱们仅仅讨论一个经常使用的Gaussian blur(高斯模糊)
.app
一般, 模糊算法会根据一个像素周围的像素为其生成一个新的色值.考虑下面的网格图片:ide
上面的每个网格单元表明了一个独立的像素, 每个像素都有一个1~10
之间的数字. 当模糊算法在计算中间像素对应的新值时, 会取其周围数字的平均值填入其中. 获得下面的结果:布局
你能够对原始图片的每个像素都执行上述过程. 上述过程只是对某一个像素周围的每一个方向取一个像素计算新的值. 你能够扩大模糊半径(上述案例的中间像素的外围像素个数)
从而增长模糊程度. 下面是个例子:
注意事项: 一般, 更大的模糊半径意味着处理图片须要更多的资源. iOS一般会将处理图片的任务转交给GPU, 去保证主线程的通畅.
人们更倾向于把注意力集中在清晰的元素上, 而不是不清晰的. 无论你信仍是不信, 这就是咱们的眼睛工做的结果. 随着物体变近或远, 眼睛随之聚焦, 这就是适应(Focusing on an object as it moves closer or further away from the eye is known as accommodation), 是他帮助你观察周围事物的深度和距离.
APP的设计师们运用了这个事实, 将屏幕上那些不重要的元素变得模糊, 从而令人们的实现保留在清晰的元素上.下面是一个示例, Twitter
客户端的截屏:
上面的图片中, 背后的用户界面几乎是不能辨别的, 这为用户提供了一个环境, 去识别他们处在哪一个层级关系中.例如, 你可能会意识到, 一旦你选择了列出帐号中的一个, 你就会返回到后面带有模糊效果的视图中.
注意: 避免在你的APP中滥用模糊效果.即便模糊能提供很好看的效果, 若是你使用不当或使用过于频繁, 它也会使人烦恼.
跟随设计标准去使用模糊能够直接吸引用户注意力, 那样你几乎不会失败.查看Apple开发者中心的iOS Human Interface Guidelines document
文档中Designing for iOS部分能够获取更多信息.
为了学习如何实现模糊效果, 你须要在Grimm
APP中添加一些.
这个APP向用户展现了不少童话故事. 当用户点击其中一个时, APP会在屏幕上展示整个故事.用户能够自定义展示的字体, 文本的对其方式, 或颜色主题(白天或夜晚).
你能够下载这个工程开始, 在Xcode中打开Grimm.xcodeproj
. 点击Main.storyboard
你会看到下面的视图:
你能够忽略最开始的controller, 它是APP的根导航控制器. 依次点击带有编号的控制器, 你将看到以下内容:
StoryListController
, 它是数据库中全部故事的列表.StoryViewController
, 它展现了点击故事的标题和具体内容.OptionsController
是包含在StoryViewController
控制器中的, 展现了支持的字体, 文本对其方式, 颜色等. 若想展现它, 只需点击详情页右上角省略号的按钮.编译并运行, 你将看到下面的初始画面:
一旦你理解了该APP是如何工做的, 就直接进入下一部分. 向该APP添加模糊效果吧.
UIVisualEffectView
添加模糊效果UIKit
提供了一整套视觉效果.UIBlurEffect
(它是UIVisualEffect
的子类), 是和你的兴趣相关的.UIBlurEffect
提供了很漂亮的视觉效果, 就像你在navigation bars
,Notification Center
,Control Center
中看到的那样. 你也能够将其用到你的APP中.
UIBlurEffect
在这个工程中, 你将使用模糊效果使OptionsController
在故事的顶部显得更加突出.让咱们投入其中吧!
打开OptionsController.swift
, 添加下面的代码到viewDidLoad:
方法的结尾处:
// 1
view.backgroundColor = .clear
// 2
let blurEffect = UIBlurEffect(style: .light)
// 3
let blurView = UIVisualEffectView(effect: blurEffect)
// 4
blurView.translatesAutoresizingMaskIntoConstraints = false
view.insertSubview(blurView, at: 0)
复制代码
依次解释下:
UIVisualEffectView
视图内容模糊起来, 它的父视图必须是透明的. 为了作到这点, 你将self.view
的背景改为了clear
UIBlurEffectStyle.light
建立了一个UIBlurEffect
. 这定义了模糊的风格. 其余支持的风格还有.extraLight
,.dark
, .extraDark
, regular
, prominent
(实际上我并无找到extraDark
).UIBlurEffect
来建立UIVisualEffectView
. 它是 UIView
的子类.它惟一的目的是描绘复杂模糊的外形和显示它.blurView
的auto-resizing
而使用constraints
, 稍后你将手动添加constraints
到它上面. 添加它到视图栈的底端. 若你在顶端添加blurView
, 这将使下面的全部元素变得模糊.如今, 你要肯定blurView
被安放在合适的位置.添加下面的代码到viewDidLoad:
方法的结尾处:
NSLayoutConstraint.activate([
blurView.heightAnchor.constraint(equalTo: view.heightAnchor),
blurView.widthAnchor.constraint(equalTo: view.widthAnchor),
])
复制代码
这些约束使blurView
的frame
和OptionsController
的view是同样的.
编译并运行, 选择一个故事, 点击省略号的按钮, 滚动文本, 你会发现模糊效果在实时的更新.
如今, 你在你的APP中实现了一个动态的模糊效果, 它不只实现简单, 并且看上去很漂亮.
模糊效果很好, 但Apple使用UIVibrancyEffect
将其带入了下一个等级, 使用它可使内容色彩更生动.
以下图:
注意:
UIVibrancyEffect
必须添加到UIVisualEffectView
的contentView
中(它已经被正确放置, 使用UIBlurEffect
配置过的)!不然不会向任何模糊的效果上添加"生动效果".
打开OptionsController.swift
, 添加下面的代码到viewDidLoad:
方法的结尾处:
// 1
let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect)
// 2
let vibrancyView = UIVisualEffectView(effect: vibrancyEffect)
vibrancyView.translatesAutoresizingMaskIntoConstraints = false
// 3
vibrancyView.contentView.addSubview(optionsView)
// 4
blurView.contentView.addSubview(vibrancyView)
复制代码
依次解释下:
blurEffect
建立一个UIVibrancyEffect
. UIVibrancyEffect
是UIVisualEffect
的另外一个子类.UIVisualEffectView
用来包含UIVibrancyEffect
效果. 这个步骤和以前建立模糊效果是同样的. 一旦你使用了Auto Layout
, 肯定将auto-resizing
关闭.optionsView
做为vibrancyView中contentView的子视图. 这将确保生动效果应用到其包含的每个元素中.接下来, 你要为vibrancyView设置自动布局的约束, 以便和blurView的尺寸同样, 以及确保optionsView在vibrancyView的中心位置.
添加下面的代码到viewDidLoad:
方法的结尾处:
NSLayoutConstraint.activate([
vibrancyView.heightAnchor.constraint(equalTo: blurView.contentView.heightAnchor),
vibrancyView.widthAnchor.constraint(equalTo: blurView.contentView.widthAnchor),
vibrancyView.centerXAnchor.constraint(equalTo: blurView.contentView.centerXAnchor),
vibrancyView.centerYAnchor.constraint(equalTo: blurView.contentView.centerYAnchor)
])
NSLayoutConstraint.activate([
optionsView.centerXAnchor.constraint(equalTo: vibrancyView.contentView.centerXAnchor),
optionsView.centerYAnchor.constraint(equalTo: vibrancyView.contentView.centerYAnchor),
])
复制代码
你还有一个事情须要注意, 看下viewDidLoad:
的开始部分, 你以及将optionsView
做为self.view
的子视图了, 而一个视图只能有一个父视图.
在viewDidLoad:
的开始部分注释掉下面的代码:
view.addSubview(optionsView)
NSLayoutConstraint.activate([
view.centerXAnchor.constraint(equalTo: optionsView.centerXAnchor),
view.centerYAnchor.constraint(equalTo: optionsView.centerYAnchor)
])
复制代码
编译并运行, 你将看到新的效果已经生效:
除非有较大差别的版本, 不然这个效果会各个元素难以辨认. 这发生了什么?
告诉你吧! 在blurView
下一层的视图是偏亮的, 而又使用了UIBlurEffectStyle.light
的效果. 这将拔苗助长, 就像上面的效果.
修改初始化blurEffect
的代码以下:
let blurEffect = UIBlurEffect(style: .dark)
复制代码
这个改变使背景和文字又来较大的差别.编译运行, 你将看到下面的效果:
在使用模糊效果时, 还有最后一点须要注意: 若是用户将模糊效果禁用了, 将会发生什么?
在模拟器或你的设备中, 打开设置, 进入General\Accessibility\Increase Contrast
, 打开Reduce Transparency
.(真机中应该是 通用\辅助功能\加强对比度\下降透明度 开关
).返回到这个APP中, 再次打开optionsView
, 你将看到下面的结果:
能够看到它没有正常工做. 这种状况下, 你最好回到开始的地方.
幸运的是, 你可使用UIAccessibilityIsReduceTransparencyEnabled()
方法判断辅助功能是否打开.你能够像下面这样修改:
guard UIAccessibilityIsReduceTransparencyEnabled() == false else {
view.addSubview(optionsView)
NSLayoutConstraint.activate([
view.centerXAnchor.constraint(equalTo: optionsView.centerXAnchor),
view.centerYAnchor.constraint(equalTo: optionsView.centerYAnchor)
])
return
}
复制代码
OK, That's all!
多说一句, 你能够进入UIAccessibility
类中, 看看能够检测哪些开关的状态的.
整个过程当中, 最大的感触是国内外的文风相差不是一丁半点啊. 国外的偏向故事风格有木有. 收获仍是很多的, 感谢你们的陪伴, 让咱们一块儿进步!