原文:http://www.raywenderlich.com/113768/adaptive-layout-tutorial-in-ios-9-getting-started譯者:@featherJ
【轉(zhuǎn)載請寫明出處俗批,多謝耐版!】
更新日期:2015/9/22:教程為iOS 9, Xcode 7 以及 Swift 2由Sam Davies更新命咐。
自適應布局的介紹引發(fā)了ios開發(fā)者們的一個巨大的轉(zhuǎn)變》谢伲現(xiàn)在,當你設計你的app的時候肮韧,你已經(jīng)可以使用一個單獨布局并且不添加任何設備適配的代碼掖鱼,使你的應用工作到所有的iOS設備上了!
這一片教程將為你介紹自適應布局悍赢。你將會學習到關(guān)于通用的storyboards决瞳,size classes,布局(layout)以及字體(font)自定義以及超有用的預覽助手編輯器(Preview Assistant Editor)左权。
在本教程中皮胡,你將從頭開始創(chuàng)建一個簡單的天氣應用的用戶界面。如果你并不是特別熱衷于自動布局也別擔心赏迟,教程的第一部分將提供一步一步的講解讓你通過自動布局來創(chuàng)建一個用戶界面屡贺。你將會驚奇的發(fā)現(xiàn)你可以不用寫一行代碼就完成這個界面。
通用的Storyboard
通用的Storyboard是你開始Adaptive Layout (自適應布局)?之旅的第一步锌杀。一個相同的Storyboard可以同時被用于iPad和iPhone設備甩栈。你并不需要為每一個設備存留一份Storyboard。
打開Xcode并且選擇Create a new Xcode project糕再,來創(chuàng)建一個新的Xcode項目:
選擇 iOS -> Application -> Single View Application量没,然后點擊下一步:
設置?Product Name(項目名)?為 AdaptiveWeather,Language(語言)?設置為Swift突想,同時設置Devices(設備) 為Universal(通用):
當項目開啟之后殴蹄,查看?Project Navigator(項目導航)?你講會看到這個單獨的storyboard文件:
Main.storyboard是一個為所有設備準備的單獨的文件。打開這個storyboard猾担,你將會看到他包含一個單獨的?view controller(視圖控制器)袭灯,但是他的尺寸可能有些古怪:
好吧,他現(xiàn)在是個正方形绑嘹!如果 Storyboard 在 Xcode 的編輯過程中匹配到某個目標設備的屏幕尺寸那就顯然不太符合“一個Storyboard作用所有設備”的原則了稽荧,所以現(xiàn)在Storyboard是用一個抽象的尺寸替代的。
選擇storyboard文件圾叼,打開File Inspector(文件檢查器) 蛤克,你將可以看到use Size Classes的選項捺癞,在你的項目中,勾上它:
這個選項默認為所有新的iOS工程勾選构挤。你可以在將舊項目升級到新項目的過程中手動激活這個勾選髓介。
構(gòu)建你的Storyboard
下面開始這個小節(jié),打開Main.storyboard文件筋现,從Object Library中拖出一個Image
View到你的view controller(視圖控制器)畫布中唐础。在 Size Inspector
(尺寸檢查器)中設置X的值為150,Y的值為20矾飞。同時設置Width(寬度)為300一膨,Height(高度)為265。
下一步洒沦,從Object Library中拖出一個View放到Image View的下面豹绪。在 Size Inspector (尺寸檢查器)中設置X為150,Y為315申眼,同時設置Width(寬度)為300瞒津,Height(高度)為265。
選擇你剛剛添加的View括尸,打開Identity Inspector(身份檢查器)巷蚪,編輯Document下的Label的內(nèi)容為TextContainer:
因為剛剛拖出來的View和View
Controller(視圖控制器)的背景色默認都為白色,所以可能不太容易找到這個View濒翻。下面我們修改一下他們的背景色屁柏。選擇View
Controller控件,打開Attributes Inspector(屬性查看器)設置Background(背景色)為#4AABF7有送。
(其實隨便一個顏色就好淌喻,因為Xcode的顏色選擇器沒沒法設置16進制顏色值)。
下一步選擇選擇TextContainer娶眷,設置它的Background(背景色)為#3780BA似嗤。
接下來你的視圖控制器看上去將是下面截圖的樣紙:
Image View和TextContainer這兩個控件是view controller的子項,下面我們將為他們設置布局約束届宠。
添加布局約束
選擇Image View并且點擊在下方自動布局欄中的Align按鈕烁落,勾選中Horizontal Center in Container(容器中的水平中心),設置值為0豌注,然后點擊Add 1 Constraint(添加一個約束)伤塌。
接下來,點擊Pin按鈕轧铁,添加一個頂部距離最近控件的距離為0的約束每聪,如下圖:
你添加的這些約束將使得Image View有一個距離頂部和距離水平中心的固定距離。現(xiàn)在我們將設置 Image
View 和 TextContainer 之間的間距。在 Image
View上按住Control鍵并拖拽至TextContainer然后釋放鼠標药薯,如下圖:
接下來將顯示一個約束內(nèi)容的菜單绑洛,選擇Vertical Spacing(垂直間距):
這個約束用于決定從 Image View 控件的底部到TextContainer控件的頂部的距離。
選擇你的 Image View 然后打開 Size Inspector(尺寸檢查器) 你會看到如下:
你會看到你已經(jīng)添加了三個約束到布局上了童本,你可以在Size
Inspector(尺寸檢查器)內(nèi)簡單的配置內(nèi)一個約束的參數(shù)真屯。在Bottom Space To:
TextContainer約束上,點擊Edit(編輯)按鈕穷娱,將會彈出一個配置約束屬性的對話框绑蔫,設置Constant的值為20:
然后點擊對話框外部,關(guān)閉這個對話框泵额。
現(xiàn)在已經(jīng)將Image View和TextContainer之間的間隔設置為了20點∨渖睿現(xiàn)在你還需要設置TextContainer另外三個邊的約束。
選擇TextContainer然后點擊底部欄的Pin圖標嫁盲,在Spacing to nearest
neighbor(約束到最近部件)部分篓叶,設置left,right和bottom的間隔為0亡资。保持Constrain to
margins(約束到邊緣)復選框為未選中狀態(tài)澜共,如果勾選這個復選框,將會移除掉視圖的外邊距锥腻。
作為參考,這個對話框應該是如下的樣紙:
點擊Add 3 constraints(添加3個約束)按鈕將這些新的約束添加到TextContainer上母谎。這樣便設置好了TextContainer距離容器的左右下邊距的約束瘦黑。
接下來你的storyboard看上去應該是如同下面截圖的樣紙:
你應該已經(jīng)注意到了在你的視圖上有一些橘黃色的和一些紅色的約束。這表示你的約束存在一些問題需要你注意一下奇唤。你可以通過storyboard的自動更新到frames的功能來調(diào)整這些約束幸斥,但是如果你現(xiàn)在這么做,Image View的尺寸將收縮為0咬扇。
這是因為現(xiàn)在這個Image View內(nèi)部還沒有任何內(nèi)容甲葬,這意味著他的內(nèi)部高度和寬度都為0经窖。如果沒有物理寬高的約束梭灿,自動布局是會依賴于部件的內(nèi)部尺寸來決定他的寬度和高度的画侣。
接下來,在Project Navigator(項目導航)中打開Images.xcassets文件堡妒。下載cloud_images.zip文件并解壓配乱,你將會發(fā)現(xiàn)里面有三個圖片。 在Finder中選擇這個三個圖片,并且拖拽他們到空的資源目錄中:
他們將創(chuàng)建一個新的圖像集搬泥,并且已經(jīng)分配好了這三個圖像:
現(xiàn)在你可以應用你的圖像集到Image View了桑寨,返回Main.storyboard 文件并選擇Image
View。切換到Attributes Inspector(屬性查看器)忿檩,在Image輸入框中輸入cloud然后選擇View -> Mode
為Aspect Fit (這幾個選項試一下就知道大概是做什么的) 如下圖:
接下來你的storyboard將看上去如下圖這樣:
但是目前仍有一些橘紅色的約束西疤,我們還有很多的事情要去做。 首先休溶,在Document Outline(文檔大綱中)選擇View Controller的View:
然后點擊在底欄中選擇 Resolve Auto Layout Issues 圖標按鈕代赁。然后在彈出的對話框中選擇All Views -> Update Frames:
然后 View Controller 內(nèi)的空間將會自動重新排列,以解決之前不太符合的約束兽掰。接下來你看到的storyboard將會是如下的樣紙:
預覽助手編輯器
通常你需要構(gòu)建并在 iPad, iPhone 4s, 5s, 6 和 6
Plus設備上運行你的項目,并在每一個旋轉(zhuǎn)方向上檢查窖壕,以保證這個新的通用storyboard瞻讽。這個過程是很麻煩的坎拐,但是Xcode6提供了一個更好
的選擇即新的Preview Assistant Editor(預覽助手編輯器)都伪。
打開Main.storyboard文件陨晶,然后點擊View -> Assistant Editor
-> Show Assistant Editor聋溜。這將編輯區(qū)分成兩部分漱病。在Jump
Bar中點擊Automatic漓穿,然后在彈出的下拉菜單中選擇Preview,然后選擇Main.storyboard。
然后新的預覽編輯器將呈現(xiàn)出一個storyboard在4英寸iPhone的屏幕的效果。如下:
通過點擊預覽框底部的 rotation icon(旋轉(zhuǎn)圖標)可以旋轉(zhuǎn)預覽效果〕ス裕現(xiàn)在預覽效果將旋轉(zhuǎn)為橫向:
這是一個模擬多設備的巨大的改進眠副,但是槽唾,還有更多忘闻!點擊預覽編輯器左下角的+按鈕將可以得到更多的可用預覽:
在列表中選擇5.5英寸的iPhone和iPad债沮,以將他們添加到預覽區(qū)中一起顯示:
注意到在橫向的iPhone中有什么奇怪的效果了么硅蹦?是的涮瞻,云圖片實在太大了!為了修復這個問題,我們將為Image View加入一個新的約束。
返回storyboard絮重,在Image View上按下Control并拖拽到View Controller的View中釋放鼠標來創(chuàng)建一個新的約束,在彈出的菜單中選擇Equal Heights(等高):
現(xiàn)在在storyboard中又出現(xiàn)了紅色的約束。這是因為你剛剛添加的約束與現(xiàn)有的約束發(fā)生了沖突,當View Controller的View保持垂直方向的時候立帖,不可能有相同的高度。
在 Document Outline (文檔大綱) 中選擇剛剛添加的約束,然后打開Attributes
Inspector (屬性檢查器)。如果第一項并沒有被設置為cloud_small.Height窿克,那么選擇第一項的下拉菜單中的Reverse
First and Second Item選項敞恋。
然后改执,設置Relation為 Less Than or Equal,設置 Multiplier (乘數(shù)) 為0.40。如下圖:
這意味著噪叙,云的圖片將在是原始尺寸债朵,或者當高度低于屏幕的40%的時候變小臭杰。
你會發(fā)現(xiàn)預覽面板的效果會在你更新約束的時候自動刷新硅卢。效果如下:
那么此時是否可以讓多個設備的預覽效果同時自動更新呢?答案是肯定的藏杖,新的Preview Assistant Editor (預覽助手編輯器)真的很有用!
要把現(xiàn)在的效果做成一個天氣的app脉顿,你還需要添加一些標簽蝌麸,用于顯示城市名和當前的溫度。
為TextContainer添加內(nèi)容
打開Main.storyboard文件,從Object Library中拖兩個Label(文本標簽)到TextContainer視圖中迫肖,然后把他們排列成如下的樣紙:
選擇上面的一個標簽然后通過Align和Pin菜單設置它的水平位置到中心,然后再添加一個 top spacing to nearest neighbor為10的約束棺克,如下圖所示:
下一步,選擇 Attributes Inspector(屬性檢查器),設置Text (文本)為Cupertino缩焦,Color(顏色)為White(白色)藐握,然后設置font(字體)為System, Thin同時Size為150他托。
現(xiàn)在你可能會發(fā)現(xiàn)文字變得無法辨認皇耗,這是因為Label的框架的緣故聋庵,我們很快就可以解決這個問題了臼疫。
現(xiàn)在選擇另一個Label料仗,同時依舊通過Align和Pin菜單設置它的水平位置到中心,然后設置bottom space to nearest neighbor為10,檢查Size Inspector(尺寸檢查器)澈段,是否和下圖一致:
通過Attributes Inspector(屬性檢查器)嘁捷,設置Text為28C骇吭,然后設置Color為White,字體為System, Thin并且字號為250歧寺。
現(xiàn)在你可以解決剛才我們提到的由于標簽的框架導致的問題了燥狰。選擇View Controller 的
view,點擊storyboard底欄的Resolve Auto Layout Issues按鈕斜筐,然后選擇All Views ->
Update Frames龙致。然后你將會看到storyboard更新為如下圖:
現(xiàn)在你發(fā)現(xiàn)兩個Label發(fā)生了重疊,看上去并不是我們所期待的樣子顷链。但是目代,在我們修復任何問題之前,可以發(fā)現(xiàn)在預覽區(qū)中iPad版本看上去是好的:
可以預見的,iPhone的字號太大了:
我們將在下一個章節(jié)中修復這個尺寸的問題榛了。
Size Classes
通用的storyboard是很給力的在讶,但是已經(jīng)發(fā)現(xiàn)為所有的設備創(chuàng)建一個通用的布局已經(jīng)有些挑戰(zhàn)性了。然而忽冻,Adaptive Layout (自適應布局)有更多的工具可以用來解決這些問題真朗。
自適應布局的核心概念之一便是size classes。Size Class是一個可以應用于任何能夠在橫向或縱向進行顯示的視圖或者視圖控制器的屬性僧诚。
Xcode提供了兩種Size Classe:Regular(正常的)和Compact(緊湊)。盡管他們與視圖的物理尺寸是有關(guān)聯(lián)的蝗碎,但是他們?nèi)匀豢梢杂靡环N語義上的尺寸呈現(xiàn)出來湖笨。
下面這個表格列出了size classe可以應用的不同的設備和方向:
這些都是設備可以應用的size classe。當然蹦骑,你也可以在視圖結(jié)構(gòu)中的任意一部分中重寫size classe慈省。這在比屏幕要小的容器中是相當有用的。
Size Classes 和你
這對你和你所設計的app到底意味著什么呢眠菇?盡管你的app是有size class的边败,但是你構(gòu)建的布局和size class是無關(guān)的,也就是說捎废,你的布局需要為所有的size class進行調(diào)整笑窜。
在涉及到自適應布局的設計的時候,這是很重要的一點登疗。首先你需要創(chuàng)建一個基本的布局排截,然后在為每一個特殊的size
class去調(diào)整你需要的size class。這里辐益,不是要把每一個size
class視為一個全新的東西去從頭設計断傲。你可以把一個自適應布局,想象成是一個樹狀的層次結(jié)構(gòu)智政,在這個層次中认罩,你可以把所有通用的設計放在父級節(jié)點中,
然后把需要單獨處理的部分放到子級的size class中续捂。
目前為止垦垂,我們幾乎還沒有提到具體的設備布局適配問題。這是因為在自適應布局的核心概念中疾忍,size class是抽象于具體設備的乔外。意思是說,一個支持自適應布局的視圖一罩,可以在一個完整的屏幕中顯示杨幼,也可以被包含與另一個視圖控制器中顯示。
這樣做也是有益于蘋果的,這樣即使設備的屏幕范圍擴大了差购,也不需要迫使程序的開發(fā)者或者設計人員從新設計他們的app四瘫。
現(xiàn)在我們將使用size class來iPhone平放時候的布局,已解決目前的用戶界面看起來不好看的問題欲逃。
使用Class Sizes
點擊底欄的w Any h Any按鈕找蜜,你將看見size class的選擇器彈出:
在這里你可以通過選擇表格單元的形式來選擇用哪種size class來呈現(xiàn)。一共有九個可能的選項:你有三個縱向的選擇和三中水平選擇(any(任意)稳析,regular(正常)洗做,compact(緊湊)),那么總共有九種size class可供選擇彰居。
注意:這里在命名上有些輕微的差異诚纸。Size class
通常是和horizontal(水平)與vertical(垂直)聯(lián)系起來的。但是陈惰,在這里卻用了width和height畦徘,在這里width 等同于
horizontal,而height 等同于 vertical抬闯。
我們現(xiàn)在的布局還不能很好的工作于compact(緊湊)的高上井辆。為了解決這個問題,我們將選擇 Any(任何)Width | Compact(緊湊) Height的size class:
于是你將立刻發(fā)現(xiàn)在編輯器中的兩個變化:
畫布的形狀變成了一個新的size class溶握。
底欄變成了藍色杯缺。這表示,你現(xiàn)在正在工作于一個特定的size class布局上奈虾。
為了改變布局夺谁,我們需要暫時的改變一些約束。在自適應布局中有這樣兩個術(shù)語installing(安裝)和uninstalling(卸載)肉微。一個約束被安裝表示它處于激活狀態(tài)了匾鸥,反之,如果約束被卸載則表示它在當前的size class中不在起作用碉纳。
然后我們通過點擊的方式選擇Image View勿负,打開Size Inspector(尺寸檢查器)。你可以看到指定視圖的所有約束:
通過單擊的方式選擇Align Center X to: Superview約束劳曹,然后按Delete鍵從當前的size class中卸載這個約束奴愉。這個約束邊立即從當前的欄中消失了,同時在Document Outline(文檔大綱)中變?yōu)榱嘶疑?/p>
注意:你可以在Size Inspector(尺寸檢查器)中This Size Class選項切換為All來查看已經(jīng)被卸載的約束铁孵。
在Size Inspector(尺寸檢查器)中雙擊被卸載的約束锭硼,你可以看到在末尾顯示的這部分:
這表示這個約束在基本布局中是被安裝的,但是在Any Width | Compact Height布局中是沒有被安裝的蜕劝。
接下來我們用同樣的方式卸載掉image view上的其他三個約束檀头。然后你的document outline(文檔大綱) 和image view的Size Inspector(尺寸檢查器)將會是如下的樣紙:
現(xiàn)在我們將為當前的size class添加需要的約束轰异。通過Align和Pin菜單來添加Vertically in the Container約束以及設置 left spacing to nearest neighbor為10:
通過 Control-拖拽 的方式從 image view拖到view controller的view中然后在彈出的菜單中選擇Equal Widths。
打開image view的Size Inspector(尺寸檢查器)然后雙擊 Equal Width to:
Superview約束暑始。如果First Item 不是cloud_small.Width搭独,你需要點擊下拉菜單中的Reverse First
and Second Item。然后設置Multiplier為0.45廊镜。
現(xiàn)在牙肝,在image view 中已經(jīng)為當前的size class設置好了約束,但是text container還是有問題的∴推樱現(xiàn)在我們需要通過約束的方式在使得在當前size class中文字部分變成居右配椭。
現(xiàn)在TextContainer內(nèi)部針對標簽的約束看起來還是可以接受的。為了使得TextContainer居右雹姊,我們先要卸載掉居左的約束颂郎。
在Document outline(文檔大綱)中選擇居左的約束,標簽為TextContainer.leader = leading:
然后通過Cmd-Delete的組合鍵來卸載掉這個約束容为。
現(xiàn)在我們需要添加兩個新的約束到TextContainer,來使得他的位置保持正確寺酪。
下面我們可以直接在Document outline(文檔大綱)中通過 Control-拖拽 的方式從TextContainer拖到view controller的View中:
然后通過 Shift-點擊 的方式加選 Top Space to Top Layout Guide和 Equal Widths坎背。然后點擊Add Constraints(添加約束)來創(chuàng)建新的約束:
打開 TextContainer 的Size Inspector(尺寸檢查器) 然后更新我們剛剛創(chuàng)建的兩個約束為如下:
Top Space to: Top Layout Guide 的 Constant值設置為0。
Equal Width to: Superview 的 Multiplier 值設置為 0.5寄雀。 注意這里你可能需要翻轉(zhuǎn)第一項和第二項得滤,如果已經(jīng)是正確的則不需要再次翻轉(zhuǎn)。 通過雙擊的方式來進入這個約束進行設置即可盒犹。
點擊底部的 Resolve Auto Layout Issues? 圖標懂更,然后選擇 All Views -> Update frames。接下來storyboard將更新成新布局的效果如下:
于是乎急膀,我們的布局就修改完成啦沮协,現(xiàn)在距離成品已經(jīng)近在咫尺了。但是仍有一些字號問題需要解決卓嫂,我們將在下一個章節(jié)中繼續(xù)講解慷暂。
適配字體
現(xiàn)在TextContainer中的字號在iPad設備上看上去還好,但是在compact(緊湊)的size class中就顯得太大了〕况ǎ現(xiàn)在我們需要在size class中來重寫字號行瑞。
注意:不想布局的重寫,對于字體的配置將會影響到基本布局餐禁。對于字體的配置并不遵從當前的size class重寫原則血久。我們需要用下面的方法來實現(xiàn)。
點擊底部的size class按鈕帮非,然后通過表格選擇當前的size class為基本的Any Width | Any Height氧吐。然后你的size class 變成為了之前我們創(chuàng)建的基本布局讹蘑。
現(xiàn)在選擇Cupertino字樣的標簽然后打開Attributes Inspector(屬性檢查器)。點擊Font左側(cè)的+號按鈕:
在彈出的菜單中選擇對應的size class 來重寫字號副砍。 選擇Compact Width -> Any Height:
這個操作會創(chuàng)建第二個字體選擇器衔肢,用于應用特殊的size class。現(xiàn)在更新新的選擇器中的字號為90:
現(xiàn)在我們用同樣的方式來更新溫度的Label豁翎,這次設置Compact Width > Any Height的字號為150角骤。
接下來在預覽區(qū)中自動更新的效果如下:
現(xiàn)在,看上去似乎好了一些心剥,但是Cupertino標簽還是被裁減了邦尊。反復調(diào)整字號到適合的大小明顯不是一個明智之
舉。Cupertino稍微有點長了优烧,但是Washington, D.C.會更長蝉揍,Kleinfeltersville,
PA會更加的長!那么我們應該如何做呢畦娄?
我們又一次需要用自動布局來解決這個問題了又沾。我們只需要簡單的設置這兩個文本標簽的寬度與TextContainer相匹配就可以了。用 Control-過拽 的方式從Cupertino標簽拖拽到TextContainer熙卡,然后選擇Equal Widths杖刷。
同樣對溫度標簽也這樣做。于是顯示的效果如下:
嗯驳癌,文本的截斷并不是我們期望的滑燃。這是當文本比容器長時候的默認填充方式。現(xiàn)在我們需要一個方式來動態(tài)的調(diào)整字號到容器的尺寸颓鲜。
選擇Cupertino標簽表窘,然后打開Attributes Inspector(屬性檢查器)。改變
AutoShrink 為 Minimum font scale 然后設置值為0.5甜滨。與此同時乐严,我們設置Text
Alignment為Centered。就像下面的樣子:
我們對溫度標簽也做同樣的處理艳吠。
現(xiàn)在再來看預覽區(qū)麦备,iPhone的布局看上去就非常好了:
在預覽區(qū)中看上去還不錯,但是我們可能還是可以花一些時間去看看是否每一樣東西都是正常工作的昭娩。iPhone的屏幕看上去像是正確的樣子:
恭喜凛篙,你已經(jīng)學到了一些基本的自適應布局的知識了。