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原理和簡單使用,感興趣的給個贊或者關注~~~

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容