【譯】UIVisualEffectView教程

_高洋_發表於2018-03-01

前言

最近感覺自己總是學習網路相關的, 有點"疲勞"了. 所以今天換個口味, 試著翻譯下國外大神的部落格. 有不好的地方還請賜教!

原文連結: www.raywenderlich.com/178486/uivi…

正文

【譯】UIVisualEffectView教程
從iOS7開始, 系統風格有了令人激動的改變, 模糊效果在APP設計中扮演了重要的角色. 若你使用適當, 模糊效果可以顯著的提高APP的視覺感受.

先讓我們一起看看蘋果是如何在系統中使用的.

【譯】UIVisualEffectView教程

其中, 控制中心是一個值得關注的示例. 模糊背景為控制中心的操作提供環境 - 雖然控制中心不屬於某一個APP, 但它卻顯示在這些活動APP的上方.

通知中心也使用了該效果, 但是, 這裡不是讓整個背景都模糊了, 每一個extension或通知都有自己模糊的背景. 這不僅看上去漂亮, 而且使每一個元素都很顯眼.

那麼如何在自己的APP中再現這些效果呢? 沒錯, 就是使用iOS內建的UIVisualEffectView! 該篇, 你將學到關於使用"模糊效果"的一切, 以使你的APP更出眾.

關於"模糊效果"你需要了解的事實

如何優雅,高效的使用需要一定的技巧. 這裡會瞭解到"模糊效果"使用到的常規演算法.

模糊效果是如何工作的

所有的模糊效果都始於一張圖片. 為了實現該效果, 你需要對圖片的每一個畫素應用模糊演算法(blurring algorithm), 這樣可以得到一個均勻的帶有模糊效果的副本. 不同種類的模糊演算法有很大差異, 並且錯綜複雜, 這裡我們僅僅討論一個常用的Gaussian blur(高斯模糊).

通常, 模糊演算法會根據一個畫素周圍的畫素為其生成一個新的色值.考慮下面的網格圖片:

【譯】UIVisualEffectView教程

上面的每一個網格單元代表了一個獨立的畫素, 每一個畫素都有一個1~10之間的數字. 當模糊演算法在計算中間畫素對應的新值時, 會取其周圍數字的平均值填入其中. 得到下面的結果:

【譯】UIVisualEffectView教程

你可以對原始圖片的每一個畫素都執行上述過程. 上述過程只是對某一個畫素周圍的每個方向取一個畫素計算新的值. 你可以擴大模糊半徑(上述案例的中間畫素的外圍畫素個數)從而增加模糊程度. 下面是個例子:

【譯】UIVisualEffectView教程

注意事項: 通常, 更大的模糊半徑意味著處理圖片需要更多的資源. iOS通常會將處理圖片的任務轉交給GPU, 去保證主執行緒的通暢.

模糊效果設計策略

人們更傾向於把注意力集中在清晰的元素上, 而不是不清晰的. 不管你信還是不信, 這就是我們的眼睛工作的結果. 隨著物體變近或遠, 眼睛隨之聚焦, 這就是適應(Focusing on an object as it moves closer or further away from the eye is known as accommodation), 是他幫助你觀察周圍事物的深度和距離.

APP的設計師們運用了這個事實, 將螢幕上那些不重要的元素變得模糊, 從而使人們的實現保留在清晰的元素上.下面是一個示例, Twitter客戶端的截圖:

【譯】UIVisualEffectView教程

上面的圖片中, 背後的使用者介面幾乎是不能辨別的, 這為使用者提供了一個環境, 去識別他們處在哪個層級關係中.例如, 你可能會意識到, 一旦你選擇了列出賬號中的一個, 你就會返回到後面帶有模糊效果的檢視中.

注意: 避免在你的APP中濫用模糊效果.即使模糊能提供很好看的效果, 如果你使用不當或使用過於頻繁, 它也會令人煩惱.

跟隨設計標準去使用模糊可以直接吸引使用者注意力, 那樣你幾乎不會失敗.檢視Apple開發者中心的iOS Human Interface Guidelines document文件中Designing for iOS部分可以獲取更多資訊.

開始動手

為了學習如何實現模糊效果, 你需要在GrimmAPP中新增一些.

這個APP向使用者展示了很多童話故事. 當使用者點選其中一個時, APP會在螢幕上展現整個故事.使用者可以自定義展現的字型, 文字的對其方式, 或顏色主題(白天或夜晚).

你可以下載這個工程開始, 在Xcode中開啟Grimm.xcodeproj. 點選Main.storyboard你會看到下面的檢視:

【譯】UIVisualEffectView教程

你可以忽略最開始的controller, 它是APP的根導航控制器. 依次點選帶有編號的控制器, 你將看到如下內容:

  • 第一個控制器是StoryListController, 它是資料庫中所有故事的列表.
  • 點選列表中的一個故事, 將來到StoryViewController, 它展示了點選故事的標題和具體內容.
  • OptionsController是包含在StoryViewController控制器中的, 展示了支援的字型, 文字對其方式, 顏色等. 若想展示它, 只需點選詳情頁右上角省略號的按鈕.

編譯並執行, 你將看到下面的初始畫面:

【譯】UIVisualEffectView教程
探索下APP, 選擇不同的故事, 點選省略號按鈕, 滑動選擇不用的字型和閱讀模式, 以便理解這些使用者介面是如何工作的.

一旦你理解了該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)
複製程式碼

依次解釋下:

  1. 為了能夠讓UIVisualEffectView檢視內容模糊起來, 它的父檢視必須是透明的. 為了做到這點, 你將self.view的背景改成了clear
  2. 使用UIBlurEffectStyle.light建立了一個UIBlurEffect. 這定義了模糊的風格. 其他支援的風格還有.extraLight,.dark, .extraDark, regular, prominent(實際上我並沒有找到extraDark).
  3. 使用上一步建立的UIBlurEffect來建立UIVisualEffectView. 它是 UIView的子類.它唯一的目的是描繪複雜模糊的外形和顯示它.
  4. 關閉了blurViewauto-resizing而使用constraints, 稍後你將手動新增constraints到它上面. 新增它到檢視棧的底端. 若你在頂端新增blurView, 這將使下面的所有元素變得模糊.

現在, 你要確定blurView被安放在合適的位置.新增下面的程式碼到viewDidLoad:方法的結尾處:

NSLayoutConstraint.activate([
  blurView.heightAnchor.constraint(equalTo: view.heightAnchor),
  blurView.widthAnchor.constraint(equalTo: view.widthAnchor),
  ])
複製程式碼

這些約束使blurViewframeOptionsController的view是一樣的.

編譯並執行, 選擇一個故事, 點選省略號的按鈕, 滾動文字, 你會發現模糊效果在實時的更新.

【譯】UIVisualEffectView教程

現在, 你在你的APP中實現了一個動態的模糊效果, 它不僅實現簡單, 而且看上去很漂亮.

使你的模糊效果更有活力

模糊效果很好, 但Apple使用UIVibrancyEffect將其帶入了下一個等級, 使用它可以使內容色彩更生動.

如下圖:

【譯】UIVisualEffectView教程

注意: UIVibrancyEffect必須新增到UIVisualEffectViewcontentView中(它已經被正確放置, 使用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)
複製程式碼

依次解釋下:

  1. 使用之前配置好的blurEffect建立一個UIVibrancyEffect. UIVibrancyEffectUIVisualEffect的另一個子類.
  2. 建立一個UIVisualEffectView用來包含UIVibrancyEffect效果. 這個步驟和之前建立模糊效果是一樣的. 一旦你使用了Auto Layout, 確定將auto-resizing關閉.
  3. optionsView作為vibrancyView中contentView的子檢視. 這將確保生動效果應用到其包含的每一個元素中.
  4. 最後, 將vibrancyView新增到blurView的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)
  ])
複製程式碼

編譯並執行, 你將看到新的效果已經生效:

【譯】UIVisualEffectView教程

除非有較大差異的版本, 否則這個效果會各個元素難以辨認. 這發生了什麼?

告訴你吧! 在blurView下一層的檢視是偏亮的, 而又使用了UIBlurEffectStyle.light的效果. 這將適得其反, 就像上面的效果.

修改初始化blurEffect的程式碼如下:

let blurEffect = UIBlurEffect(style: .dark)
複製程式碼

這個改變使背景和文字又來較大的差異.編譯執行, 你將看到下面的效果:

【譯】UIVisualEffectView教程

更進一步

在使用模糊效果時, 還有最後一點需要注意: 如果使用者將模糊效果禁用了, 將會發生什麼?

在模擬器或你的裝置中, 開啟設定, 進入General\Accessibility\Increase Contrast, 開啟Reduce Transparency.(真機中應該是 通用\輔助功能\增強對比度\降低透明度 開關).返回到這個APP中, 再次開啟optionsView, 你將看到下面的結果:

【譯】UIVisualEffectView教程

可以看到它沒有正常工作. 這種情況下, 你最好回到開始的地方.

幸運的是, 你可以使用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類中, 看看可以檢測哪些開關的狀態的.

結語

整個過程中, 最大的感觸是國內外的文風相差不是一丁半點啊. 國外的偏向故事風格有木有. 收穫還是不少的, 感謝大家的陪伴, 讓我們一起進步!

  • 部分圖片來源於網路,如有侵權,請告知。
  • 如有錯誤,還請指出。共勉!
  • 您的喜歡是最大的讚賞。

相關文章