iOS 9自適應(yīng)布局(Adaptive Layout):入門

原文: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更新。

自適應(yīng)布局的介紹引發(fā)了ios開發(fā)者們的一個巨大的轉(zhuǎn)變。現(xiàn)在,當你設(shè)計你的app的時候,你已經(jīng)可以使用一個單獨布局并且不添加任何設(shè)備適配的代碼,使你的應(yīng)用工作到所有的iOS設(shè)備上了!

這一片教程將為你介紹自適應(yīng)布局。你將會學(xué)習(xí)到關(guān)于通用的storyboards,size classes,布局(layout)以及字體(font)自定義以及超有用的預(yù)覽助手編輯器(Preview Assistant Editor)。

在本教程中,你將從頭開始創(chuàng)建一個簡單的天氣應(yīng)用的用戶界面。如果你并不是特別熱衷于自動布局也別擔心,教程的第一部分將提供一步一步的講解讓你通過自動布局來創(chuàng)建一個用戶界面。你將會驚奇的發(fā)現(xiàn)你可以不用寫一行代碼就完成這個界面。

通用的Storyboard

通用的Storyboard是你開始Adaptive Layout (自適應(yīng)布局)?之旅的第一步。一個相同的Storyboard可以同時被用于iPad和iPhone設(shè)備。你并不需要為每一個設(shè)備存留一份Storyboard。

打開Xcode并且選擇Create a new Xcode project,來創(chuàng)建一個新的Xcode項目:

選擇 iOS -> Application -> Single View Application,然后點擊下一步:

設(shè)置?Product Name(項目名)?為 AdaptiveWeather,Language(語言)?設(shè)置為Swift,同時設(shè)置Devices(設(shè)備) 為Universal(通用):

當項目開啟之后,查看?Project Navigator(項目導(dǎo)航)?你講會看到這個單獨的storyboard文件:

Main.storyboard是一個為所有設(shè)備準備的單獨的文件。打開這個storyboard,你將會看到他包含一個單獨的?view controller(視圖控制器),但是他的尺寸可能有些古怪:

好吧,他現(xiàn)在是個正方形!如果 Storyboard 在 Xcode 的編輯過程中匹配到某個目標設(shè)備的屏幕尺寸那就顯然不太符合“一個Storyboard作用所有設(shè)備”的原則了,所以現(xiàn)在Storyboard是用一個抽象的尺寸替代的。

選擇storyboard文件,打開File Inspector(文件檢查器) ,你將可以看到use Size Classes的選項,在你的項目中,勾上它:

這個選項默認為所有新的iOS工程勾選。你可以在將舊項目升級到新項目的過程中手動激活這個勾選。

構(gòu)建你的Storyboard

下面開始這個小節(jié),打開Main.storyboard文件,從Object Library中拖出一個Image

View到你的view controller(視圖控制器)畫布中。在 Size Inspector

(尺寸檢查器)中設(shè)置X的值為150,Y的值為20。同時設(shè)置Width(寬度)為300,Height(高度)為265。

下一步,從Object Library中拖出一個View放到Image View的下面。在 Size Inspector (尺寸檢查器)中設(shè)置X為150,Y為315,同時設(shè)置Width(寬度)為300,Height(高度)為265。

選擇你剛剛添加的View,打開Identity Inspector(身份檢查器),編輯Document下的Label的內(nèi)容為TextContainer:

因為剛剛拖出來的View和View

Controller(視圖控制器)的背景色默認都為白色,所以可能不太容易找到這個View。下面我們修改一下他們的背景色。選擇View

Controller控件,打開Attributes Inspector(屬性查看器)設(shè)置Background(背景色)為#4AABF7。

(其實隨便一個顏色就好,因為Xcode的顏色選擇器沒沒法設(shè)置16進制顏色值)。

下一步選擇選擇TextContainer,設(shè)置它的Background(背景色)為#3780BA。

接下來你的視圖控制器看上去將是下面截圖的樣紙:

Image View和TextContainer這兩個控件是view controller的子項,下面我們將為他們設(shè)置布局約束。

添加布局約束

選擇Image View并且點擊在下方自動布局欄中的Align按鈕,勾選中Horizontal Center in Container(容器中的水平中心),設(shè)置值為0,然后點擊Add 1 Constraint(添加一個約束)。

接下來,點擊Pin按鈕,添加一個頂部距離最近控件的距離為0的約束,如下圖:

你添加的這些約束將使得Image View有一個距離頂部和距離水平中心的固定距離。現(xiàn)在我們將設(shè)置 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(編輯)按鈕,將會彈出一個配置約束屬性的對話框,設(shè)置Constant的值為20:

然后點擊對話框外部,關(guān)閉這個對話框。

現(xiàn)在已經(jīng)將Image View和TextContainer之間的間隔設(shè)置為了20點。現(xiàn)在你還需要設(shè)置TextContainer另外三個邊的約束。

選擇TextContainer然后點擊底部欄的Pin圖標,在Spacing to nearest

neighbor(約束到最近部件)部分,設(shè)置left,right和bottom的間隔為0。保持Constrain to

margins(約束到邊緣)復(fù)選框為未選中狀態(tài),如果勾選這個復(fù)選框,將會移除掉視圖的外邊距。

作為參考,這個對話框應(yīng)該是如下的樣紙:

點擊Add 3 constraints(添加3個約束)按鈕將這些新的約束添加到TextContainer上。這樣便設(shè)置好了TextContainer距離容器的左右下邊距的約束。

接下來你的storyboard看上去應(yīng)該是如同下面截圖的樣紙:

你應(yīng)該已經(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(項目導(dǎo)航)中打開Images.xcassets文件。下載cloud_images.zip文件并解壓,你將會發(fā)現(xiàn)里面有三個圖片。 在Finder中選擇這個三個圖片,并且拖拽他們到空的資源目錄中:

他們將創(chuàng)建一個新的圖像集,并且已經(jīng)分配好了這三個圖像:

現(xiàn)在你可以應(yīng)用你的圖像集到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將會是如下的樣紙:

預(yù)覽助手編輯器

通常你需要構(gòu)建并在 iPad, iPhone 4s, 5s, 6 和 6

Plus設(shè)備上運行你的項目,并在每一個旋轉(zhuǎn)方向上檢查,以保證這個新的通用storyboard。這個過程是很麻煩的,但是Xcode6提供了一個更好

的選擇即新的Preview Assistant Editor(預(yù)覽助手編輯器)。

打開Main.storyboard文件,然后點擊View -> Assistant Editor

-> Show Assistant Editor。這將編輯區(qū)分成兩部分。在Jump

Bar中點擊Automatic,然后在彈出的下拉菜單中選擇Preview,然后選擇Main.storyboard。

然后新的預(yù)覽編輯器將呈現(xiàn)出一個storyboard在4英寸iPhone的屏幕的效果。如下:

通過點擊預(yù)覽框底部的 rotation icon(旋轉(zhuǎn)圖標)可以旋轉(zhuǎn)預(yù)覽效果。現(xiàn)在預(yù)覽效果將旋轉(zhuǎn)為橫向:

這是一個模擬多設(shè)備的巨大的改進,但是,還有更多!點擊預(yù)覽編輯器左下角的+按鈕將可以得到更多的可用預(yù)覽:

在列表中選擇5.5英寸的iPhone和iPad,以將他們添加到預(yù)覽區(qū)中一起顯示:

注意到在橫向的iPhone中有什么奇怪的效果了么?是的,云圖片實在太大了!為了修復(fù)這個問題,我們將為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 (屬性檢查器)。如果第一項并沒有被設(shè)置為cloud_small.Height,那么選擇第一項的下拉菜單中的Reverse

First and Second Item選項。

然后,設(shè)置Relation為 Less Than or Equal,設(shè)置 Multiplier (乘數(shù)) 為0.40。如下圖:

這意味著,云的圖片將在是原始尺寸,或者當高度低于屏幕的40%的時候變小。

你會發(fā)現(xiàn)預(yù)覽面板的效果會在你更新約束的時候自動刷新。效果如下:

那么此時是否可以讓多個設(shè)備的預(yù)覽效果同時自動更新呢?答案是肯定的,新的Preview Assistant Editor (預(yù)覽助手編輯器)真的很有用!

要把現(xiàn)在的效果做成一個天氣的app,你還需要添加一些標簽,用于顯示城市名和當前的溫度。

為TextContainer添加內(nèi)容

打開Main.storyboard文件,從Object Library中拖兩個Label(文本標簽)到TextContainer視圖中,然后把他們排列成如下的樣紙:

選擇上面的一個標簽然后通過Align和Pin菜單設(shè)置它的水平位置到中心,然后再添加一個 top spacing to nearest neighbor為10的約束,如下圖所示:

下一步,選擇 Attributes Inspector(屬性檢查器),設(shè)置Text (文本)為Cupertino,Color(顏色)為White(白色),然后設(shè)置font(字體)為System, Thin同時Size為150。

現(xiàn)在你可能會發(fā)現(xiàn)文字變得無法辨認,這是因為Label的框架的緣故,我們很快就可以解決這個問題了。

現(xiàn)在選擇另一個Label,同時依舊通過Align和Pin菜單設(shè)置它的水平位置到中心,然后設(shè)置bottom space to nearest neighbor為10,檢查Size Inspector(尺寸檢查器),是否和下圖一致:

通過Attributes Inspector(屬性檢查器),設(shè)置Text為28C,然后設(shè)置Color為White,字體為System, Thin并且字號為250。

現(xiàn)在你可以解決剛才我們提到的由于標簽的框架導(dǎo)致的問題了。選擇View Controller 的

view,點擊storyboard底欄的Resolve Auto Layout Issues按鈕,然后選擇All Views ->

Update Frames。然后你將會看到storyboard更新為如下圖:

現(xiàn)在你發(fā)現(xiàn)兩個Label發(fā)生了重疊,看上去并不是我們所期待的樣子。但是,在我們修復(fù)任何問題之前,可以發(fā)現(xiàn)在預(yù)覽區(qū)中iPad版本看上去是好的:

可以預(yù)見的,iPhone的字號太大了:

我們將在下一個章節(jié)中修復(fù)這個尺寸的問題。

Size Classes

通用的storyboard是很給力的,但是已經(jīng)發(fā)現(xiàn)為所有的設(shè)備創(chuàng)建一個通用的布局已經(jīng)有些挑戰(zhàn)性了。然而,Adaptive Layout (自適應(yīng)布局)有更多的工具可以用來解決這些問題。

自適應(yīng)布局的核心概念之一便是size classes。Size Class是一個可以應(yīng)用于任何能夠在橫向或縱向進行顯示的視圖或者視圖控制器的屬性。

Xcode提供了兩種Size Classe:Regular(正常的)和Compact(緊湊)。盡管他們與視圖的物理尺寸是有關(guān)聯(lián)的,但是他們?nèi)匀豢梢杂靡环N語義上的尺寸呈現(xiàn)出來。

下面這個表格列出了size classe可以應(yīng)用的不同的設(shè)備和方向:

這些都是設(shè)備可以應(yīng)用的size classe。當然,你也可以在視圖結(jié)構(gòu)中的任意一部分中重寫size classe。這在比屏幕要小的容器中是相當有用的。

Size Classes 和你

這對你和你所設(shè)計的app到底意味著什么呢?盡管你的app是有size class的,但是你構(gòu)建的布局和size class是無關(guān)的,也就是說,你的布局需要為所有的size class進行調(diào)整。

在涉及到自適應(yīng)布局的設(shè)計的時候,這是很重要的一點。首先你需要創(chuàng)建一個基本的布局,然后在為每一個特殊的size

class去調(diào)整你需要的size class。這里,不是要把每一個size

class視為一個全新的東西去從頭設(shè)計。你可以把一個自適應(yīng)布局,想象成是一個樹狀的層次結(jié)構(gòu),在這個層次中,你可以把所有通用的設(shè)計放在父級節(jié)點中,

然后把需要單獨處理的部分放到子級的size class中。

目前為止,我們幾乎還沒有提到具體的設(shè)備布局適配問題。這是因為在自適應(yīng)布局的核心概念中,size class是抽象于具體設(shè)備的。意思是說,一個支持自適應(yīng)布局的視圖,可以在一個完整的屏幕中顯示,也可以被包含與另一個視圖控制器中顯示。

這樣做也是有益于蘋果的,這樣即使設(shè)備的屏幕范圍擴大了,也不需要迫使程序的開發(fā)者或者設(shè)計人員從新設(shè)計他們的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布局上。

為了改變布局,我們需要暫時的改變一些約束。在自適應(yīng)布局中有這樣兩個術(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約束以及設(shè)置 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。然后設(shè)置Multiplier為0.45。

現(xiàn)在,在image view 中已經(jīng)為當前的size class設(shè)置好了約束,但是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值設(shè)置為0。

Equal Width to: Superview 的 Multiplier 值設(shè)置為 0.5。 注意這里你可能需要翻轉(zhuǎn)第一項和第二項,如果已經(jīng)是正確的則不需要再次翻轉(zhuǎn)。 通過雙擊的方式來進入這個約束進行設(shè)置即可。

點擊底部的 Resolve Auto Layout Issues? 圖標,然后選擇 All Views -> Update frames。接下來storyboard將更新成新布局的效果如下:

于是乎,我們的布局就修改完成啦,現(xiàn)在距離成品已經(jīng)近在咫尺了。但是仍有一些字號問題需要解決,我們將在下一個章節(jié)中繼續(xù)講解。

適配字體

現(xiàn)在TextContainer中的字號在iPad設(shè)備上看上去還好,但是在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è)的+號按鈕:

在彈出的菜單中選擇對應(yīng)的size class 來重寫字號。 選擇Compact Width -> Any Height:

這個操作會創(chuàng)建第二個字體選擇器,用于應(yīng)用特殊的size class。現(xiàn)在更新新的選擇器中的字號為90:

現(xiàn)在我們用同樣的方式來更新溫度的Label,這次設(shè)置Compact Width > Any Height的字號為150。

接下來在預(yù)覽區(qū)中自動更新的效果如下:

現(xiàn)在,看上去似乎好了一些,但是Cupertino標簽還是被裁減了。反復(fù)調(diào)整字號到適合的大小明顯不是一個明智之

舉。Cupertino稍微有點長了,但是Washington, D.C.會更長,Kleinfeltersville,

PA會更加的長!那么我們應(yīng)該如何做呢?

我們又一次需要用自動布局來解決這個問題了。我們只需要簡單的設(shè)置這兩個文本標簽的寬度與TextContainer相匹配就可以了。用 Control-過拽 的方式從Cupertino標簽拖拽到TextContainer,然后選擇Equal Widths。

同樣對溫度標簽也這樣做。于是顯示的效果如下:

嗯,文本的截斷并不是我們期望的。這是當文本比容器長時候的默認填充方式。現(xiàn)在我們需要一個方式來動態(tài)的調(diào)整字號到容器的尺寸。

選擇Cupertino標簽,然后打開Attributes Inspector(屬性檢查器)。改變

AutoShrink 為 Minimum font scale 然后設(shè)置值為0.5。與此同時,我們設(shè)置Text

Alignment為Centered。就像下面的樣子:

我們對溫度標簽也做同樣的處理。

現(xiàn)在再來看預(yù)覽區(qū),iPhone的布局看上去就非常好了:

在預(yù)覽區(qū)中看上去還不錯,但是我們可能還是可以花一些時間去看看是否每一樣?xùn)|西都是正常工作的。iPhone的屏幕看上去像是正確的樣子:

恭喜,你已經(jīng)學(xué)到了一些基本的自適應(yīng)布局的知識了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容