iOS 7給蘋果設備帶來了全新的用戶界面(UI)。iOS 7在UI上的變化是自其誕生以來最大的。iOS 7專註於三個重要的特點:清晰、依從和層次。理解這三個特點很重要,因為這有助於設計跟原生的系統內置應用一樣的應用。 本章將介紹iOS 7引入的一些重要變化以及如何讓應用使用這些新特性。前半章展示開發 ...
iOS 7給蘋果設備帶來了全新的用戶界面(UI)。iOS 7在UI上的變化是自其誕生以來最大的。iOS 7專註於三個重要的特點:清晰、依從和層次。理解這三個特點很重要,因為這有助於設計跟原生的系統內置應用一樣的應用。
本章將介紹iOS 7引入的一些重要變化以及如何讓應用使用這些新特性。前半章展示開發者應該瞭解的重要的UI範式,利用這些範式可以使應用更上一層樓。後半章展示如何把已有的iOS 6應用遷移到iOS 7上,並且需要的話,也可以保持向後相容性。
2.1 清晰、依從和層次
清晰(clarity)很簡單,就是對用戶來說表達的意思是清晰的。大部分iOS用戶會抓住一些碎片時間使用應用,他們會打開Facebook,查看通知或者新聞訂閱,發佈狀態更新或照片,然後關閉應用。至少在iPhone上,很少有應用是用戶長時間使用的。事實上統計表明,對於大部分應用,用戶每次只會用80秒左右。這意味著開發者必須在極短的時間內把信息傳遞給用戶,因此應該把最重要的信息清晰地展示在屏幕上。舉個例子,如果開發天氣應用,溫度和天氣狀況是用戶最感興趣的兩塊信息,要把UI設計得足夠簡潔,讓用戶不需要在視野範圍內尋找就能直接看到。
依從(deference)是說操作系統不會提供和應用的UI競爭的UI,相反,它依從於應用及其內容。這意味著每個應用都會有獨一無二的外觀和體驗。在iOS 7之前,應用的UI是用戶看到的在系統提供的導航欄和工具欄內部的東西,鍍層效果、不規則邊框和漸變色被依從於其背後內容的半透明欄取代。操作系統的預設應用依從於內容,而UI在大部分情況下只起輔助作用。
為iOS 7設計的應用應該具有層次(depth)的概念。控制項和內容應該處於不同的層,從home screen開始就是這樣,視差效果給人感覺圖標是浮在最上面的一層上,模態化的警告框也有類似效果。通知中心和控制中心也有層次,它們用的是模糊和半透明而不是視差效果。
2.2 動畫、動畫、動畫
使用iOS 7後開發者發現的第一件事可能就是應用的視覺擬真(擬物)沒有了。陰影很不明顯,幾乎看不出來,拋光按鈕完全消失了。真實世界的擬物元素,比如備忘錄(iPhone)和通訊錄(iPad)的人造革,也都不見了。
最重要的是,應用程式視窗預設就是全屏的,狀態欄現在是半透明的,浮在應用程式視窗的上方。註意,直到iOS 6,應用程式的全屏和狀態欄的半透明一直都只是可選的。在iOS 6中,必須把導航欄的translucent
屬性設置為YES
,並且把視圖控制器的wantsFullScreenLayout
設置為YES
才行。在iOS 7中所有的視窗預設都是這麼設置的。
一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是一個我的iOS交流群:1012951431, 分享BAT,阿裡面試題、面試經驗,討論技術, 大家一起交流學習成長!希望幫助開發者少走彎路。
儘管視覺擬真沒有了,iOS 7強化了運動擬真。運動擬真的強化從鎖屏開始。試著拖動攝像頭按鈕把鎖屏界面“提起來”,然後從屏幕中間“掉下來”,你會看到鎖屏界面會在碰到屏幕底部時彈起來。現在再試著把鎖屏界面往屏幕底部推一下來“撞擊”,你會看到彈得更厲害了,就跟真實世界的物體撞到錶面一樣。所以,擬物並沒有完全從iOS 7中消失,之前版本的iOS強調視覺擬物,而iOS 7更加重視物理擬物。
iOS 7仍然是擬物的,只不過不是強調視覺擬物而是物理擬物,屏幕上的物體遵從物理定律,其行為類似於真實世界的物體。
2.2.1 UIKit Dynamics
在應用中實現物理特性很簡單,iOS 7引入了一個新類UIDynamicAnimator
,用來模擬真實世界的物理定律。開發者可以創建一個UIDynamicAnimator
對象並將其添加到視圖上,這個視圖通常是視圖控制器的根視圖,在UIKit Dynamics上下文中通常也被稱為引用視圖,引用視圖的子視圖現在就會基於其關聯的行為遵從物理定律。
行為可以通過聲明定義並添加到視圖。事實上,任何遵從UIDynamicItem
協議的對象都可以添加行為。UIView
及其子類(包括UIControl
)遵從這個協議,這意味著屏幕上可見的任何東西幾乎都可以關聯一種行為。
這裡還有一件有意思的事情,UICollectionViewLayoutAttributes
遵從UIDynamicItem
協議,這樣可以讓集合視圖的元素有動力學行為。預設的信息應用就是一個例子。
2.2.2 UIMotionEffect
物理擬物還沒完。主屏幕上的視差效果,警告框好像浮動在視圖上方的效果,Safari新的切換選項卡UI在傾斜設備時會顯示“更多”內容,這些都是真實行為的模擬。用UIMotionEffect
很容易就能為應用添加這類特性。iOS 7中的一個新類UIInterpolatingMotionEffect
,能讓開發者不費吹灰之力就添加這類效果。可以把UIMotionEffect
理解為跟CAAnimation
類似。CAAnimation
會對其所屬的層做動畫,UIMotionEffect
會對其所屬的視圖做動畫。CAAnimation
的動畫是時間的函數,UIMotionEffect
的動畫則是設備動作的函數。我們會在第19章詳細介紹UIKit Dynamics和UIMotionEffect。
CAAnimation
動畫是時間的函數,UIMotionEffect
是設備動作的函數。
2.3 著色
UIView
有了一個新屬性,叫做tintColor
,可以給應用著色。所有作為其他視圖的子視圖存在的UI元素都會在未設置tintColor
的情況下使用父視圖的tintColor
。這意味著給應用程式的視窗設置tintColor
就可以得到全局的著色。
這裡要註意的很重要的一點是當模態化視圖出現時,iOS 7會將其背後所有的UI元素變模糊。如果開發者有一個自定義視圖,並且用了父視圖的tintColor
來做一些自定義渲染,就要覆蓋tintColorDidChange
方法來更新變化。
也可以在Xcode的故事板編輯器的File inspector面板中設置tintColor
。
2.4 用半透明實現層次和上下文
UIKit Dynamics和UIMotionEffect能幫助用戶理解應用中的空間深度。iOS 7中還有一個強化空間深度概念的特性是在大部分模態化視窗上統一使用了模糊和半透明效果。控制中心和通知中心用一種精細的方式模糊了背景,以便用戶能知道背後是什麼。
iOS 7通過直接讀取顯存來實現這種效果。遺憾的是,iOS 7沒有提供SDK來讓開發者輕鬆實現這種效果,可能是出於安全上的考慮。比如說,無法這麼做:
self.view.blurRadius = 50.0f; self.view.saturationDelta = 2.0f;
不過,有一個WWDC講座中的示例代碼有UIImage
的分類,UIImage+ImageEffects
(本書的示例代碼中有)允許實現這種效果,儘管這種方法很難用也不直觀。但是你想超越極限,這也是你閱讀本書的原因,不是嗎?所以,在自己的應用中實現這種效果吧。
現在要展示如何創建一個看起來像通知中心或者控制中心背景的圖層。首先創建一個單視圖應用,挑一張漂亮的背景圖加上,再添加一個按鈕。接下來寫一個按鈕動作處理方法,彈出一個會將後面的背景模糊的視圖。
捷徑(或者說投機取巧)是創建一個不可見的UIToolbar
並使用它的圖層,而不是創建新圖層。不過這種技巧很容易失效,所以不推薦。更好的辦法是用iOS 7新的UIScreenshotting介面截屏,切割截屏圖片,為其添加模糊效果,並把模糊的圖片作為彈出視圖的背景。
來看看代碼:
用UIImage+ImageEffects
創建模糊的彈出層(SCTViewController.m)
// 創建圖層** self.layer = [CALayer layer]; self.layer.frame = CGRectMake(80, 100, 160, 160); [self.view.layer addSublayer:self.layer]; **// 截屏** float scale = [UIScreen mainScreen].scale; UIGraphicsBeginImageContextWithOptions(self.view.frame.size, YES, scale); [self.view drawViewHierarchyInRect:self.view.frame afterScreenUpdates:NO]; __block UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); **// 裁剪截圖** CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, CGRectMake(self.layer.frame.origin.x * scale, self.layer.frame.origin.y * scale, self.layer.frame.size.width * scale, self.layer.frame.size.height * scale)); image = [UIImage imageWithCGImage:imageRef]; **// 添加效果** image = [image applyBlurWithRadius:50.0f tintColor: [UIColor colorWithRed:0 green:1 blue:0 alpha:0.1] saturationDeltaFactor:2 maskImage:nil]; // 放到新建的圖層上 self.layer.contents = (__bridge id)(image.CGImage);
applyBlurWithRadius:tintColor:saturationDeltaFactor:maskImage:
方法位於UIImage+ImageEffects
分類中,包括分類在內的完整代碼可以從本書網站上下載。
圖2-1顯示了代碼運行的效果。
【插入P25圖】
圖2-1 應用在iOS 7中運行時彈出視圖前後的截屏
2.5 動態字體
在iOS 7中,用戶可以設置文字大小。內置的郵件、日曆以及其他大部分應用都會按照這個設置動態改變文字大小。註意增大文字大小並不總是能讓字體的磅數變大。當文字大小設置的值可能會讓小號字體無法辨認時,iOS 7會自動加粗文字。為應用增加動態字體支持後,還可以在設置應用中動態改變文字大小。不過,iOS 7的動態字體有一個缺點:在寫作本章時,還不支持自定義字體。第21章會介紹動態字體。
2.6 自定義過渡效果
iOS 7的另一個新特性是蘋果在大部分內置應用中儘量減少了屏幕切換的使用。打開日曆應用,點擊一個日期,日期視圖以自定義的過渡動畫效果從月視圖中出現。類似地,創建新事件時,改變事件的開始和結束時間也是用動畫實現自定義過渡。註意,這個動畫在之前版本的iOS中是導航控制器的預設推入頁面操作動畫。還有一個例子是照片應用中的照片選項卡,萬年不變的相機膠卷被一個使用自定義過渡在年度視圖、精選視圖、時刻視圖和單張照片視圖之間切換的集合視圖替代了。iOS 7新的UI範式強調讓用戶知道自己在哪裡,而不是讓他們迷失在推入的無數視圖控制器中。大部分情況下,這些動畫都用自定義過渡實現,如圖2-2所示。
【插入P26圖】
圖2-2 日曆應用的屏幕,顯示使用自定義過渡的屏幕
為iOS 7設計應用時,要認真考慮使用自定義過渡是否對於讓用戶知道自己在哪兒有所幫助。iOS 7 SDK增加了介面,能毫無困難地實現這些動畫。
2.6.1 自定義過渡類型
iOS 7的SDK支持兩類自定義過渡:自定義視圖控制器過渡和互動式視圖控制器過渡。自定義視圖控制器過渡之前也能實現,要用到故事板和自定義聯線。互動式視圖控制器過渡則讓用戶利用手勢(通常是拖動)控制過渡的過程(從開始到結束)。因此當用戶拖動或快速滑動手指時,會從一個視圖控制器過渡到另一個。
當過渡是時間的函數時,通常是自定義視圖控制器過渡,是手勢識別器的參數或類似事件的函數時,通常是互動式視圖控制器過渡。
比如,可以認為導航控制器的推入過渡(就像iOS 6那樣)是一種自定義視圖控制器過渡,而UIPageViewController
則是互動式視圖控制器過渡。使用UIPageViewController
在視圖之間翻頁時,過渡跟時間無關,頁面的過渡跟著手指的移動走,所以這是互動式視圖控制器過渡。而UINavigationController
過渡(在iOS 6中)在一段時間內發生,所以這類過渡是自定義視圖控制器過渡。
iOS 7 SDK允許開發者自定義幾乎任何類型的過渡:視圖控制器的presentation和dismissal、UINavigationController
的推入和彈出過渡、UITabbarController
的過渡(UITabbarController
預設不對視圖控制器做動畫),甚至是集合視圖的佈局變化過渡。
自定義視圖控制器過渡比互動式視圖控制器過渡更易使用。本章會展示如何創建自定義視圖控制器過渡。互動式視圖控制器過渡相對較難使用,第20章會介紹這個主題。
2.7 把應用過渡(遷移)到iOS 7
到目前為止,本章介紹了iOS 7中引入的主要UI範式並實現了其中一種:模糊效果。在本節中,我們會展示如何把應用從iOS 6過渡到iOS 7。
你已經知道了,iOS 7的UI和之前的版本大不相同。因此,你得瞭解大量的API變化。可能的話,完全放棄對iOS 6的支持,因為iOS 7的升級率要比iOS 6高得多。不過,如果業務需要支持iOS 6,繼續閱讀下一節,我們會展示如何在不犧牲iOS 6的情況下支持iOS 7。
2.7.1 UIKit變化
在iOS 7中,幾乎所有的UI元素都發生了變化。按鈕沒有邊框,開關和分段控制項變小了,滑塊和進度條變細了。如果使用自動佈局,大部分變化都不會對你有什麼影響。如果沒有使用自動佈局,那麼是時候把nib文件升級到自動佈局了。如果不使用自動佈局,那麼在3.5寸和4寸設備上支持iOS 6和iOS 7就需要寫大量的佈局代碼。
如果你之前一直不想使用自動佈局,那麼現在必須開始學習了。Xcode 5中的自動佈局要比Xcode 4.x中的好用得多,本書第6章會更為詳細地講解自動佈局。
2.7.2 自定義設計
一般來說大部分應用都會用自定義設計圖來做應用皮膚,開發者需要仔細考慮如何設計。原因是iOS 7的設計是非常“平”的,視覺擬物削弱了很多。這麼做是因為在iPhone 4之前,幾乎所有的屏幕(手機/PC/Mac)像素密度都在70 ppi~160 ppi(每英寸像素數)之間。iPhone 4的視網膜屏將像素密度增加到了320 ppi。這個像素密度接近健康人眼所能接受的最高程度,再多就是人眼接受不到的多餘數據了。這也是印刷業採用300 ppi的原因。
印刷業不需要模擬拋光發亮的按鈕、不規則邊框、漸變或者藝術字體。你什麼時候見過廣告牌或者雜誌封面的圖上加上人造拋光或者發亮的效果?沒有。為什麼?因為不需要。(有些雜誌有光澤,但那是真的光澤。)事實上,軟體設計師利用拋光、發亮按鈕來讓他們的設計在(當時的)低解析度(70 ppi~160 ppi)屏幕上看起來比較好看。
而iPhone 4屏幕的像素密度達到了接近高印刷質量的雜誌的程度,為UI添加光澤和發光效果就沒有必要了。這就是Twitterrific 5、LetterPress和Clear(代辦事項應用)甚至在蘋果之前就大量減少了界面效果的原因。Windows Phone 7界面從第一天開始就沒有拋光、發亮或者陰影。
今天,除了iPad mini,蘋果在2011年和2012年間發佈的幾乎所有iOS設備都採用了視網膜屏。扁平化設計是未來。給UI設計光澤在iOS 7中看起來就過時了。
如果用了拋光或是發亮按鈕,你就得重新設計UI了。問問自己,這個UI在雜誌上列印出來會是什麼樣子的。你得像印刷業的設計師那樣考慮問題,而不是軟體業的設計師。
2.7.3 支持iOS6
寫向後相容iOS 6的代碼要比以前難,因為iOS 7是其誕生以來的一次大升級。如果你的應用需要支持iOS 6,首先讓iOS 6的應用跟iOS 7的外觀類似,這意味著並非要在iOS 7中用扁平按鈕卻在iOS 6中用拋光按鈕,而是把iOS 6的按鈕也變扁平。首先改變iOS 6版本的設計,使其看起來像iOS 7版本。對結果滿意後,再添加iOS 7獨有的特性。
1. 應用圖標
iOS 7使用的圖標大小和iOS 6不同,對於iPhone應用是120×120,對於iPad應用是152×152。你得為應用更換這些略大的圖標,避免使用拋光或者發亮,“Icon already includes gloss effects (UIPrerenderedIcon)”這個設置在iOS 7下不起作用,可能最終會廢棄。
2. 啟動圖
啟動圖現在應該是480點高(對於iPhone 5來說是568)。iOS 7中啟動圖會渲染在狀態欄下麵,如果你用的啟動圖太短,屏幕底部會出現黑邊。
3. 狀態欄
iOS 7中的狀態欄是半透明的,會將其背後的內容模糊。在iOS 6版本的應用中,應該用拋光不那麼多的設計圖(甚至完全沒有光澤)確保狀態欄是扁平的。在iOS 7中,視圖控制器會延伸到全屏,位於狀態欄下麵。在iOS 6版本的應用中,可以把狀態欄的樣式改為UIStatusBarStyleBlackTranslucent
來模擬這種行為。
4. 導航欄
iOS 7中的導航欄預設也是半透明的,而且沒有陰影,底部邊界倒是有一條細線。可以考慮為iOS 6版本的應用添加類似的效果來取代陰影。
在iOS 6中,設置tintColor
會改變導航欄的顏色,要在iOS 7中得到同樣的效果,需要設置barTintColor
。導航欄上的返回按鈕也變了,以前是帶邊框的按鈕,現在則是箭頭和文字。記住,就算是預設按鈕也不帶邊框了,而且UIButtonTypeRoundedRect
也廢棄了。在iOS 6版本的應用中,可以用導航欄的外觀代理協議(appearance proxy protocol )來自定義返回按鈕,併為返回按鈕設置類似於iOS 7版本的圖片。
導航欄的背景圖通常是320×44,有時候開發者可能會用略高的帶陰影的導航欄。在iOS 7中,導航欄的背景圖延伸到了狀態欄下方,而不是像iOS 6那樣在視圖控制器上方。避免使用高於44點的導航欄背景圖。你可能得重新設計背景圖並且考慮用別的辦法添加陰影。iOS 6為UINavigationBar
引入了shadowImage
屬性,可以用這個屬性設置導航欄陰影。
5. 工具欄
工具欄也是半透明的,不過更重要的是工具欄上的按鈕沒有邊框。如果按鈕不多於3個,可以考慮用文本按鈕而不是圖片按鈕。比如iOS 7的音樂應用中的正在播放頁面用文本按鈕表示重覆、隨機和創建(如圖2-3所示)。
【插入P29圖1】
圖2-3 iOS 7中控制按鈕的截圖
6. 視圖控制器
在iOS 7中,所有視圖控制器都是全屏佈局的。可以在iOS 7中支持新佈局,在iOS 6中保留舊佈局,但是應用看起來會有點過時。要擁抱變化,在iOS 6版本中用全屏佈局。將視圖控制器的wantsFullscreenLayout
屬性設置成YES
就可以在iOS 6中實現這一點。註意,這個屬性在iOS 7中廢棄了,而且在iOS 7中將這個屬性設置成NO
的行為是未定義的。
在iOS 7中也可以使用不透明的條欄,這可以通過Interface Builder的選項控制視圖在半透明/不透明條欄下方的樣子,如圖2-4所示。
【插入P29圖2】
圖2-4 Interface Builder中將視圖延伸到半透明條欄下方的選項
Interface Builder的nib文件中還有Top Layout Guide和Bottom Layout Guide(只有打開自動佈局才有),也可以用這些引導點設置約束條件。所以開發者可以讓按鈕總是離Top Layout Guide50個點。
7. 表格視圖控制器
表格視圖控制器,尤其是分組表格視圖樣式,不再有內嵌效果了。分割線變成了內嵌的,從圖片開始,到屏幕邊緣結束。單元分割線變細了,顏色也變淺了。
section頭顏色也變淺了,而且是純色,不再是漸變色了。在iOS 7版本的應用中可以給sectionIndexBackgroundColor
設置值來改變顏色。在iOS 6中,只能在tableView:viewForHeaderInSection:
委托方法中返回外觀和iOS 7版本類似的視圖。
還有一個重要的變化是選擇樣式。iOS 6提供了兩種樣式:藍色和灰色。用內置樣式時,文本的前景色會從黑色變成白色。在iOS 7中不會這樣,高亮色只是一種淺灰色,覆蓋UITableViewCell
子類的setSelected:animated:
和setHighlighted:animated:
可以模擬這種行為。
預設的滑動刪除手勢以前是從左向右滑,現在是從右向左滑。如果開發者正考慮在表格視圖單元中用從右向左滑的手勢來顯示菜單或做一個動作,就得考慮用別的方法來實現了。
8. 拖動手勢
iOS 7預設在所有應用中使用兩種拖動手勢,第一種是UIScreenEdgePanGestureRecognizer
,在導航控制器中,從屏幕邊緣滑動可以讓用戶回到上一個視圖。這個行為是預設的。如果你在使用像Facebook的舊版應用那樣的漢堡菜單(俗稱側滑菜單或者側滑面板),就得考慮關掉顯示菜單的手勢。事實上,隨著iOS 7的發佈,Facebook完全拋棄了漢堡菜單,採用了選項卡欄。第二種手勢是從屏幕底部拖動的手勢,可以顯示控制中心。如果你的應用使用了類似的手勢來調用某個功能,就得重新設計界面了。
9. 警告框和操作列表
警告框和操作列表總是使用系統的預設樣式,除非開發者創建自己的。如果有自定義的警告框,可以考慮加入UIMotionEffect
以便讓其看起來像是浮在視圖控制器上方。在iOS 6中建立層次概念要靠陰影,而在iOS 7中則用運動效果。在iOS 6中模擬運動效果很難。除非願意花費時間和精力,否則就在iOS 6中保留UI元素的陰影吧。
2.8 小結
本章介紹了新的UI範式,還有新設計背後的深層次原因,並且深入講解了iOS 7中不同的UI相關的技術。最後,我們介紹瞭如何將應用遷移到iOS 7,並且(可選地)維持向後相容性。要做到寫出在iOS 6和iOS 7上都能工作的代碼並且外觀在兩個系統上看起來都很好是很難的(至少是相對而言)。如果業務允許你投入時間和資源,那就做吧。否則,把精力集中在iOS 7每個可能的功能上,讓應用脫穎而出。
iOS 7為開發者提供了在App Store大獲成功的機遇,舉幾個例子:iOS 7專用的待辦事項應用,iOS 7專用的Twitter客戶端,iOS 7專用的日曆應用。理解了iOS 7的UI範式,是時候大幹一把了。