UIKit框架(四十九) —— UIVisualEffectView原理和简单使用(一)

版本记录

版本号 时间
V1.0 2020.11.29 星期日

前言

iOS中有关视图控件用户能看到的都在UIKit框架里面,用户交互也是通过UIKit进行的。感兴趣的参考上面几篇文章。
1. UIKit框架(一) —— UIKit动力学和移动效果(一)
2. UIKit框架(二) —— UIKit动力学和移动效果(二)
3. UIKit框架(三) —— UICollectionViewCell的扩张效果的实现(一)
4. UIKit框架(四) —— UICollectionViewCell的扩张效果的实现(二)
5. UIKit框架(五) —— 自定义控件:可重复使用的滑块(一)
6. UIKit框架(六) —— 自定义控件:可重复使用的滑块(二)
7. UIKit框架(七) —— 动态尺寸UITableViewCell的实现(一)
8. UIKit框架(八) —— 动态尺寸UITableViewCell的实现(二)
9. UIKit框架(九) —— UICollectionView的数据异步预加载(一)
10. UIKit框架(十) —— UICollectionView的数据异步预加载(二)
11. UIKit框架(十一) —— UICollectionView的重用、选择和重排序(一)
12. UIKit框架(十二) —— UICollectionView的重用、选择和重排序(二)
13. UIKit框架(十三) —— 如何创建自己的侧滑式面板导航(一)
14. UIKit框架(十四) —— 如何创建自己的侧滑式面板导航(二)
15. UIKit框架(十五) —— 基于自定义UICollectionViewLayout布局的简单示例(一)
16. UIKit框架(十六) —— 基于自定义UICollectionViewLayout布局的简单示例(二)
17. UIKit框架(十七) —— 基于自定义UICollectionViewLayout布局的简单示例(三)
18. UIKit框架(十八) —— 基于CALayer属性的一种3D边栏动画的实现(一)
19. UIKit框架(十九) —— 基于CALayer属性的一种3D边栏动画的实现(二)
20. UIKit框架(二十) —— 基于UILabel跑马灯类似效果的实现(一)
21. UIKit框架(二十一) —— UIStackView的使用(一)
22. UIKit框架(二十二) —— 基于UIPresentationController的自定义viewController的转场和展示(一)
23. UIKit框架(二十三) —— 基于UIPresentationController的自定义viewController的转场和展示(二)
24. UIKit框架(二十四) —— 基于UICollectionViews和Drag-Drop在两个APP间的使用示例 (一)
25. UIKit框架(二十五) —— 基于UICollectionViews和Drag-Drop在两个APP间的使用示例 (二)
26. UIKit框架(二十六) —— UICollectionView的自定义布局 (一)
27. UIKit框架(二十七) —— UICollectionView的自定义布局 (二)
28. UIKit框架(二十八) —— 一个UISplitViewController的简单实用示例 (一)
29. UIKit框架(二十九) —— 一个UISplitViewController的简单实用示例 (二)
30. UIKit框架(三十) —— 基于UICollectionViewCompositionalLayout API的UICollectionViews布局的简单示例(一)
31. UIKit框架(三十一) —— 基于UICollectionViewCompositionalLayout API的UICollectionViews布局的简单示例(二)
32. UIKit框架(三十二) —— 替换Peek and Pop交互的基于iOS13的Context Menus(一)
33. UIKit框架(三十三) —— 替换Peek and Pop交互的基于iOS13的Context Menus(二)
34. UIKit框架(三十四) —— Accessibility的使用(一)
35. UIKit框架(三十五) —— Accessibility的使用(二)
36. UIKit框架(三十六) —— UICollectionView UICollectionViewDiffableDataSource的使用(一)
37. UIKit框架(三十七) —— UICollectionView UICollectionViewDiffableDataSource的使用(二)
38. UIKit框架(三十八) —— 基于CollectionView转盘效果的实现(一)
39. UIKit框架(三十九) —— iOS 13中UISearchController 和 UISearchBar的新更改(一)
40. UIKit框架(四十) —— iOS 13中UISearchController 和 UISearchBar的新更改(二)
41. UIKit框架(四十一) —— 使用协议构建自定义Collection(一)
42. UIKit框架(四十二) —— 使用协议构建自定义Collection(二)
43. UIKit框架(四十三) —— CALayer的简单实用示例(一)
44. UIKit框架(四十四) —— CALayer的简单实用示例(二)
45. UIKit框架(四十五) —— 支持DarkMode的简单示例(一)
46. UIKit框架(四十六) —— 支持DarkMode的简单示例(二)
47. UIKit框架(四十七) —— 自定义Calendar Control的简单示例(一)
48. UIKit框架(四十八) —— 自定义Calendar Control的简单示例(二)

开始

首先我们看下主要内容:

在本UIVisualEffectView教程中,您将学习模糊技术的工作方式,以及如何向您自己的应用添加自然模糊和鲜艳(vibrancy)效果。内容来自翻译

接着,看下写作环境:

Swift 5, iOS 14, Xcode 12

下面就是正文啦

自从iOS 7中iOS的设计发生巨大变化以来,模糊在应用程序设计中就发挥了重要作用。 如果使用得当,模糊可以显着改善应用程序的可用性和外观。

苹果在系统级别使用模糊效果非常好。 两个著名的示例是Control Center和新的iOS 14Widget Center。 这些中使用的模糊背景保留了操作的上下文 - Control Center and Widget Center不是他们自己的应用,而是在活动应用上方显示的面板。

Notification Center也使用模糊效果,但是每个通知中心扩展或通知都有自己的模糊背景,而不是模糊整个背景。 除了看起来漂亮之外,这种模糊还可以帮助每个元素突出正确的数量。

那么,如何在自己的应用中重新创建这些类型的模糊呢? 使用内置的UIVisualEffectView! 在本教程中,您将学到使用模糊使应用脱颖而出所需的所有知识,包括:

  • How blurs work
  • Strategies for designing blurs
  • How to use UIVisualEffectView

下面我们继续。

打开入门项目。要了解如何使用模糊处理,您可以将模糊处理效果添加到全新的Brothers Grimm童话应用程序中-恰当地命名为Grimm

该应用程序显示一个童话故事库。 当用户点击童话故事时,该应用会显示整个故事。 用户可以自定义显示字体,文本对齐甚至颜色主题。

在Xcode中打开Grimm.xcodeproj。 打开Main.storyboard,然后查看应用程序中包含的视图控制器,如下所示:

您可以忽略上图中的第一个视图控制器,因为它只是应用程序的根导航控制器,它具有StoryListViewController作为其根视图控制器。 轮流使用每个编号的视图控制器,您将看到以下内容:

  • 1) 第一个视图控制器是StoryListViewController,它显示数据库中所有童话的列表。
  • 2) 轻按列表中的一个故事会将用户引导到StoryViewController,该故事将显示所选童话的标题和文本。
  • 3) OptionsViewController包含在StoryViewController中,并显示可用的字体,文本对齐方式和颜色选项。 要显示它,请点击导航栏中的右上角设置图标。

构建并运行。 您会看到如下所示的初始屏幕:

在探索应用程序时玩得开心。 选择不同的故事,点击设置图标,然后滑动到不同的字体和阅读模式,以了解用户界面的功能。

现在,在继续之前,重要的是要进一步了解模糊。 下一部分将介绍模糊的工作原理,并讨论模糊的设计准则。


How Blurs Work

所有模糊都始于图像。 要实现模糊,请对图像中的每个像素应用模糊算法(blurring algorithm)。 生成的图像将包含原始图像的均匀模糊版本。 模糊算法的样式和复杂性各不相同;在本部分中,您将了解一种称为高斯模糊(Gaussian blur)的常见算法。

模糊算法通常检查图像的每个像素,然后使用周围的像素为该像素计算新的颜色值。 例如,考虑以下理论图像网格:

上方网格中的每个像元代表一个单独的像素,并且每个像素的值都在110之间。请考虑算法正在评估中心像素的情况。 该算法对周围像素的值进行平均,并将该平均值插入到中心像素中,从而产生以下新像素网格:

该算法对原始图像中的每个像素重复此过程。

上面的示例仅查看每个方向上的一个像素以创建新的平均值。 但是扩展模糊半径会增加图像中的模糊量,如下图所示:

3px and 16px Gaussian blur applied to an image

注意:通常,模糊半径越大,处理图像所需的处理能力就越大。 iOS将大多数图像处理活动卸载到GPU,以保持主线程空闲。

您现在对模糊的工作原理有所了解,但是模糊的设计又如何呢? 下一节将介绍有关如何以及何时使用它们的一些准则。


Blur Design Strategies

人类倾向于注意关注的要素而忽略不关注的要素。 信不信由你,这是我们眼睛运作的自然结果。 当物体靠近或远离眼睛时聚焦在物体上被称为accommodation。 这可以帮助您感知周围物体的深度和距离。

应用设计人员利用这一事实,模糊屏幕上无关紧要的项目,以将用户的注意力吸引到其余未模糊的元素上,如iOS本机Photos应用的以下屏幕截图所示:

在上图中可以识别出背景中的用户界面,但几乎看不到。这为用户提供了有关他们在导航层次结构中的位置的contextual awareness 。例如,关闭显示的菜单后,您希望返回到后台的模糊视图。

注意:请注意在移动应用程序中过度使用模糊效果。尽管模糊可以提供美观的效果,但是如果使用不当或使用频率过高,它们可能会分散注意力和烦人。

遵循标准的设计方法,使用模糊效果将用户的注意力吸引到重要的事物上,并且您很少会出错。有关此主题的更多信息,请参见iOS Human Interface Guidelines文档的Materials部分。

有了这些,现在该开始应用模糊效果了。


Blur Effects Using UIVisualEffectView

UIKit提供了完整的视觉效果套件。 UIBlurEffectUIVisualEffect的子类,它特别相关,因为它提供了您在导航栏,通知中心和控制中心中看到的漂亮的模糊效果,并且您也可以在应用程序中使用它。

1. Adding a UIBlurEffect

在这个项目中,您将使用模糊效果使OptionsViewController脱颖而出。

打开OptionsViewController.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)

这是上面代码中的工作:

  • 1) 为了使UIVisualEffectView实际上模糊内容,其超级视图必须是透明的。 要使其透明,请将视图的背景色更改为透明。
  • 2) 使用UIBlurEffect.Style.light样式创建UIBlurEffect。 这定义了模糊样式。 有很多不同的风格。 查看文档check the documentation以查看完整列表。
  • 3) 使用刚刚创建的模糊创建UIVisualEffectView。 此类是UIView的子类。 其唯一目的是定义和显示复杂的视觉效果。
  • 4) 禁止将auto-resizing masks转换为blurView上的constraints - 您稍后将手动添加约束-并将其添加到视图堆栈的底部。 如果在视图顶部添加blurView,它将模糊其下的所有控件!

现在,您需要确保blurView与其余视图正确布局。

将以下代码添加到viewDidLoad的末尾:

NSLayoutConstraint.activate([
  blurView.topAnchor.constraint(equalTo: view.topAnchor),
  blurView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
  blurView.heightAnchor.constraint(equalTo: view.heightAnchor),
  blurView.widthAnchor.constraint(equalTo: view.widthAnchor)
])

这些约束使blurViewframeOptionsViewControllerframe保持一致。

构建并运行。 选择一个童话,点击设置按钮,然后滚动文本。 您会实时看到模糊更新。

切换Reading Mode并注意背景模糊如何变化:

现在,您的应用程序具有动态模糊效果,不仅易于实现,而且看起来也很棒。

2. Adding Vibrancy to Your Blur

模糊效果很棒。但是像往常一样,Apple通过UIVibrancyEffect将其提升到了一个新的水平。 当与UIVisualEffectView结合使用时,Vibrancy会调整内容的颜色,使内容更生动。

下图显示了充满活力(vibrancy)的方式如何使标签和图标从屏幕上弹出,同时与背景本身融合在一起:

上图的左侧显示了正常的标签和按钮,而右侧显示了具有鲜艳度(vibrancy)的标签和按钮。

注意:必须将UIVibrancyEffect添加到已使用UIBlurEffect对象设置和配置的UIVisualEffectViewcontentView中。 否则,就不会有任何模糊效果,可以使它充满活力!

打开OptionsViewController.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)

在上面的代码中,您:

  • 1) 创建一个UIVibrancyEffect,它使用您之前设置的blurEffect。 UIVibrancyEffect是UIVisualEffect的另一个子类。
  • 2) 创建一个UIVisualEffectView来包含vibrancy效果。 此过程与创建模糊完全相同。 由于您使用的是Auto Layout,因此请确保在此处禁用auto-resizing translation
  • 3) 添加optionsView作为动态视图的contentView的子视图。 这样可以确保将vibrancy effect应用于包含所有控件的视图。
  • 4) 将vibrancy view添加到模糊视图的contentView中以完成效果。

接下来,您需要为vibrancy view设置Auto Layout constraints,以使其具有与模糊视图相同的尺寸。 然后,请确保将选项视图置于vibrancy view的中心。

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)
])

构建并运行。 导航到选项视图以查看您的vibrancy effect

除非您具有高对比度的视觉效果,否则vibrancy effect会导致难以阅读标签和控件。 这是怎么回事?

嗯-模糊视图后面的内容很浅,您正在应用UIBlurEffect.Style.light效果。 当然,这适得其反。

更改viewDidLoad()顶部附近初始化blurEffect的行:

let blurEffect = UIBlurEffect(style: .dark)

light样式到dark样式的变化增加了背景和文本之间的对比度。

构建并运行。 您现在正经历着真正的vibrancy


Accessibility

但是,在涉及模糊时,您需要考虑的最后一件事:如果用户禁用了模糊该怎么办?

在模拟器或设备上,打开Settings应用程序,然后转到Accessibility ▸ Display & Text Size,然后启用Reduce Transparency。 返回应用程序,然后再次打开选项视图。

好吧,那有点黑。 回到您的开始是一个更好的选择。

幸运的是,您可以使用UIAccessibility.isReduceTransparencyEnabled检查是否启用了此辅助功能设置。 如果您知道此设置已启用,则可以更改应用程序的外观和行为。

viewDidLoad()中设置视图的背景色之前,请添加以下内容:

guard !UIAccessibility.isReduceTransparencyEnabled else {
  return
}

此代码检查是否启用了Reduce Transparency。 如果是这样,请忽略您刚才编写的所有代码,并返回到原始布局,而不会造成任何模糊。

构建并运行,您将看到选项菜单的背景不再模糊:

您已经了解了如何使图像模糊以及如何使用UIVisualEffectView创建实时模糊效果。 您可以轻松地将高级模糊效果添加到自己的应用程序中! 您可以深入了解更多的效果和选项,而继续探索的最佳位置是在Apple’s official UIVisualEffectView documentation文档中。

UIVisualEffectViews实时更新,因此您可以通过这些效果实现各种奇怪而美妙的事情。 尝试着使所有内容模糊不清时,请记住本教程前面部分中有关仅在适当的地方谨慎使用这些效果的提示。

后记

本篇主要讲述了UIVisualEffectView原理和简单使用,感兴趣的给个赞或者关注~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容