前言
最近感覺自己總是學習網路相關的, 有點"疲勞"了. 所以今天換個口味, 試著翻譯下國外大神的部落格. 有不好的地方還請賜教!
正文
從iOS7開始, 系統風格有了令人激動的改變, 模糊效果在APP設計中扮演了重要的角色. 若你使用適當, 模糊效果可以顯著的提高APP的視覺感受.先讓我們一起看看蘋果是如何在系統中使用的.
其中, 控制中心是一個值得關注的示例. 模糊背景為控制中心的操作提供環境 - 雖然控制中心不屬於某一個APP, 但它卻顯示在這些活動APP的上方.
通知中心也使用了該效果, 但是, 這裡不是讓整個背景都模糊了, 每一個extension或通知都有自己模糊的背景. 這不僅看上去漂亮, 而且使每一個元素都很顯眼.
那麼如何在自己的APP中再現這些效果呢? 沒錯, 就是使用iOS內建的UIVisualEffectView
! 該篇, 你將學到關於使用"模糊效果"的一切, 以使你的APP更出眾.
關於"模糊效果"你需要了解的事實
如何優雅,高效的使用需要一定的技巧. 這裡會瞭解到"模糊效果"使用到的常規演算法.
模糊效果是如何工作的
所有的模糊效果都始於一張圖片. 為了實現該效果, 你需要對圖片的每一個畫素應用模糊演算法(blurring algorithm)
, 這樣可以得到一個均勻的帶有模糊效果的副本. 不同種類的模糊演算法有很大差異, 並且錯綜複雜, 這裡我們僅僅討論一個常用的Gaussian blur(高斯模糊)
.
通常, 模糊演算法會根據一個畫素周圍的畫素為其生成一個新的色值.考慮下面的網格圖片:
上面的每一個網格單元代表了一個獨立的畫素, 每一個畫素都有一個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是如何工作的, 就直接進入下一部分. 向該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的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
類中, 看看可以檢測哪些開關的狀態的.
結語
整個過程中, 最大的感觸是國內外的文風相差不是一丁半點啊. 國外的偏向故事風格有木有. 收穫還是不少的, 感謝大家的陪伴, 讓我們一起進步!
注
- 部分圖片來源於網路,如有侵權,請告知。
- 如有錯誤,還請指出。共勉!
- 您的喜歡是最大的讚賞。