IOS 6 自動佈局 入門 2

來自Ray:恭喜各位!大家已經經過宣傳ios feast提早解鎖了第一個有關IOS6的教程。 ios

目前這份教程只是咱們的新書iOS 6 By Tutorials裏面某個章節的精簡版。這份教程由一樣著做過iOS Apprentice Series的Matthijs Hollemans 完成,開始體驗吧! 程序員

這份教程由IOS 教程小組的組員Matthijs Hollemans發佈,Matthijs既是一位經驗豐富的IOS程序員又是一名資深老到的界面設計者。. spring


這系列教程的第一部分你見識到了舊的「struts-and-springs」 模式不能簡單的解決全部的用戶界面佈局問題。新的IOS 6特徵是一種解決方案,但由於這個技術是如此的有效,它使用起來仍是有點小棘手的。在這系列教程的第二部分也是最後一部分, 你將繼續學習constraint的概念以及如何運用他們! canvas

大膽嘗試constraint

也許你已經注意在canvas裏面到有些T型狀對象看上去比其餘的要粗一點。這些加粗的,咱們稱之爲user constraints,你刪除它們後的效果和刪除細的是不一樣的。當你刪除一個user constraints,Interface Builder常常會自動在刪除的地方放置一個不可刪除的constraint來代替之。我立刻就會講到爲何會這樣。
在文檔概要圖中,user constraint有一個藍色按鈕: xcode

User constraints document outline

 

選中 Vertical Space (40) constraint 而後按一下鍵盤上的刪除按鈕。 在兩個按鈕之間的T形狀對象消失了,取而代之的是一個新的直接鏈接屏幕底部的Vertical Space constraint : app

After deleting user constraint

新的constraint有一個紫色的按鈕,而且圖中它的線沒有被加粗,這也就表明着它是不可刪除的。如今這兩個再也不在垂直方向鏈接在一塊兒了。儘管因爲Leading Alignment constraint 而依然左邊對齊着。
爲何會發生這種事情? 爲何 Interface Builder對按鈕發出了一個新的 Vertical Constraint , 甚至你尚未告訴它要刪除這麼一個constraint?答案是: iview

對於每個view都必需要有足夠的constraints來對其進行位置以及大小的控制。 dom

當用到 Auto Layout時,這是一條最重要的規則。若是對於一個view沒有足夠的 constraints, 它的 Auto Layout 將不能決定它的位置以及大小。 這種佈局是被認爲無效的。待會你會看到幾個無效佈局的例子。 ide

Interface Builder會盡可能幫你避免佈局無效。這兩個按鈕的尺寸是能夠知道的由於他們根據他們包含的文本,背景圖以及其餘的一些東西-固定尺寸內容是能夠肯定下來他們的尺寸,還記得不?因此這不會是一個問題,上方按鈕的X-位置也能夠經過它的左邊界與下方按鈕的左邊界對齊來獲取,而下方按鈕又一直保持着底部居中。如今惟一不肯定的就是它的Y-位置。 工具

以前的話,這兩個按鈕用一個 Vertical Space相連。這個條件足夠能推導出上方按鈕的Y-位置。但若是你刪除了Vertical Space,上方按鈕就沒有依據來定位它在view裏的垂直位置了。由於Auto Layout不知道如何決定它的Y位置,因此它不能在屏幕中顯示出來。

爲了不這種狀況發生,Interface Builder須要從新在view中找一個離按鈕底部邊界最近的地方「pin」它。

Pin all the buttons

有趣的是,當你從新運行程序而且轉動屏幕至景觀方向時,仍是以前的效果嘛。這也是正常的,但你的設計確實從根本上就不一樣了:這兩個按鈕如今都與窗體的底部相連。這也就意味着,當下方按鈕移動時,上方的按鈕不會跟着它一塊兒動了。(注意這個解決方案也不算很好,好很差取決於和你理想的效果是否相同。在這個例子中,你明顯是但願這兩個間有一個vertical connnetion。)

咱們證實一下,選中底下那個按鈕的和屏幕底邊的一個Vertical Space constraint,而後到Attributes inspector ,它的常量如今是「Auto」,目前它是一個標準尺寸,如今把它改成40。
由於這兩個按鈕選擇沒有連接,因此如今只有下方的按鈕往上面移動了;上方的按鈕仍是保持原位:

Only bottom button moves up

注意當改變 constraint常量值時會將它提高爲一個 加粗的 「user」 constraint。

針和銷

如今讓咱們把兩個按鈕在再次鏈接在一塊兒。目前爲止你經過把按鈕拖進canvas來獲得了一些constraints,你能夠在稍後作這些。按住Cmd鍵而後同時選中它們,在Editor菜單, 而後選擇PinVertical Spacing。

你也能夠經過右下角的小面板菜單來作這個constraint:

Shortcut menu pin

它會彈出以下菜單:
Pin menu

 

先無論你選擇了哪一種方法, 這個操做在兩個按鈕之間添加了一個新的constraint:

Pin vertical spacing

這個新的constraint是一個有常量爲20 points的Vertical Space 。這僅僅是由於當你把兩個按鈕鏈接起來的時候,他們之間的距離是20 points。

注意原來從上方按鈕到屏幕底部的Vertical Space仍是存在的。這個constraint是Vertical Space(104)- 如今已經不須要,因此刪了它吧。

以前當你刪除一個藍色constraint的時候,一個紫色會出現而且取代它。如今這種事情不會發生了,由於剩下的constraints已經足夠表達清楚全部view的位置。只有在現有constraint不夠的狀況下,Interface Builder纔會添加新的constraint。

如今你的constraints應該以下所示:

Restored constraints

選中底部的 Vertical Space (經過在canvas上點擊) 而後把它的constant 40的值改回爲標準值。這步不只僅應該把下方按鈕往下移,上方的按鈕也該移動。由於如今他們又被鏈接在一塊兒了。

一個動態運行小測試

如今你知道的一點基礎知識有:如何使用guides來放置控件,如何使他們相連對齊,如何在空間之間設置空白空間。在這篇教程後,你也會了解到Align and Pin 菜單的其餘選項。

使用Interface Builder 來鼓搗constraints是很是不錯的, 但如今讓咱們來看看,在程序運行的時候這個是如何工做的。在?ViewController.m 中加入以下方法:

- (IBAction)buttonTapped:(UIButton *)sender { if ([[sender titleForState:UIControlStateNormal] isEqualToString:@"X"]) [sender setTitle:@"A very long title for this button" forState:UIControlStateNormal]; else [sender setTitle:@"X" forState:UIControlStateNormal]; }

這個方法解釋爲經過觸發按鈕事件來簡單的切換按鈕標題的長短。從Interface Builder裏面給這兩個按鈕鏈接方法:對每一個按鈕按住Ctrl拖至File’s Owner 而後在組裏面選擇buttonTapped:

運行程序看看這會怎麼樣。而且同時在景觀方向和肖像方向設置測試。

Long and short titles

不論你觸碰的是哪一個按鈕,如今的頁面佈局老是可以符合你提出的contraints:

  • 在水平方向,下方的按鈕老是在窗口中水平居中。
  • 下方的按鈕老是和窗口的底部保持20 points距離。
  • 上方的按鈕老是和下方的保持左邊界對齊。

這是你設置的整個用戶界面的規範。

你能夠爲了樂趣,同時在Interface Builder選中兩個按鈕,而後從Align菜單選擇Right Edges。而後運行程序注意觀察這其中的區別。

重複地,但如今請選擇AlignHorizontal Centers。這會使上方的按鈕中心和下方的按鈕的中心對齊。如今運行程序看看這些按鈕是如何工做的。

修復寬度

Pin 菜單有一個 Widths Equally選項。 若是你的兩個view設置了這個constraint,那麼Auto Layout 會一直保持兩個view的寬度相等,這個寬度值取決於較寬的那個view。讓咱們來對這個作一個實驗。

選中這兩個按鈕而後在菜單裏選擇?PinWidths Equally。?這步操做爲兩個按鈕添加了一個新的constraint:

Buttons widths equally

提示: 若是兩個按鈕的任意一個與superview有一個你不想要的constraint,那麼請再次同時選中兩個按鈕而後執行 AlignHorizontal Centers選項。

在這系列教程的第一部分,你實際上是已經見識過了這類constraint。這個看上去和普通的T型狀對象相似,但其實在這T型狀對象的中間有一個圈,圈裏是有一個等於號的。

看,在文檔概要圖裏又多了一個 ?Equal Widths constraint:

Equal widths in document outline

如今改變其中一個按鈕的標籤內容也會同時改變到另外個按鈕的尺寸了。

把下方按鈕的標籤內容改至 「X」,讓它足夠小。你能夠注意到上方按鈕的尺寸不在兼容它的內容了:

Top button text no longer fits

那麼Interface Builder是如何知道要選用哪一個按鈕的尺寸的呢? 若是你足夠細心的話,你會發現有一個, Width constraint 被加到了上方按鈕:

Width constraint on truncated button in document outline

Width constraint on truncated button

Interface Builder 強制上方按鈕變小,爲了知足Equal Widths constraint這個限制條件。

很明顯這不是你想要的結果,因此請選擇上方按鈕而後在Editor菜單裏爲它選擇Size to Fit Content(或者按快捷鍵 Cmd =)。如今,按鈕裏面的文本又能所有看到了 –  或者更科學的說,這個按鈕可以根據包含的文本而調整大小了 – 另外它的Width constraint也消失了。

運行程序而後點擊按鈕。如今兩個按鈕一直保持相同寬度了,不論哪一個按鈕的長度比較寬:

Buttons equal widths in app

固然當兩個按鈕都變得很是短時,他們仍是會一塊兒縮小到相等寬度。除非有個constraint來作限制,否則的話按鈕控件是會根據他本身包含的內容來很少很多的調整本身的尺寸到一個恰當的大小。這個叫什麼功能呢?對的,這就是固有內容尺寸。

固有內容尺寸

在 Auto Layout功能出現以前, 你一般會設置你的各類控件該有多大,或者在經過定製他們的frame、bounds屬性來改變大小,或者直接在Interface Builder來改變他們的大小。 但目前的狀況是大部分的控件徹底有能力基於它們的內容來計算出自生所要佔的空間大小。

一個label可以經過設置在它上面的文本長度以及文本字體來計算出本身的寬和高。相似地,button,能夠經過在它帶有背景的文本以及一些圓角的填充來計算出適合本身的寬和高。

這也適用於不少分段控件,如一些progress bars,還有許多的其餘控件,儘管有一些是有一個預約義的高,可是它寬仍是能夠設置的。

這就是所謂的 固有尺寸內容, 在Auto Layout這是一個重要的概念。在按鈕的操做中你已經見識到了吧。. Auto Layout 會先問你的空間他們有多大,而後在基於空間給出的信息將他們展現到屏幕上去。

你也能夠不使用它,但你要明確設置這個空間的Width 或者 Height constraint。若是你這麼作了,那麼 Interface Builder 爲自動生成一個你設置的constraint。若是想要再次恢復固有內容尺寸的話,你只需從新使用Size to Fit Content 操做, 另外以前你設置的 Width or Height constraints會自動消失.

一般來講,你使用固有內容尺寸功能就夠了,但有些狀況下這功能仍是盡如人意的。想象一下,當你須要在UIImageView上設置一個image的時候,若是那個image要比屏幕大的多,你一般會給image設置一個合適的寬度以及高度來適應UIImageView的內容尺寸,除非你想讓imageview來自動幫你從新設置image的dimensions。

若是對一個按鈕設置一個固定的 Width constraint,狀況會怎麼樣? 雖然按鈕可以計算本身的尺寸,可是你能經過給他設置一個固定的尺寸來使它的計算無效。選中上方的按鈕而後在菜單選擇PinWidth。 看,按鈕上方有了一個固定的T型狀對象了:

Button fixed width constraint

由於這類的constraint只應用於按鈕自己,而不是它的superview,它被列在文檔概要圖中的按鈕對象下方。就像你剛纔所作的,如今這個按鈕的固定尺寸被設爲了73 points。

運行程序而後點擊按鈕,看看發生了什麼?按鈕的文本內容改變了,它再也不所有顯示內容了由於缺乏足夠多的空間:

Button text clipped

由於上方按鈕有個固定的尺寸又由於兩個按鈕被要求是同一尺寸,因此他們不會再縮小和放大了。

提示: 你一般的設計理念是不會對一個按鈕設置Width constraint – 最好的狀況是讓按鈕使用它本身的固有內容尺寸 – 但當你遇到過一個你但願控件自動改變尺寸而它沒有改變的佈局問題時,那麼最好請屢次確認一下Interface Builder裏面有沒有一個固定的 Width constraint。

仍是多玩一會這個東西吧以便於你真正掌握 對view對象的pinning 以及aligning 。由於不是全部的現象都很明顯,因此你最好對它有一種感受。可是請你記住,對於必需要有足夠多的constraints,  Auto Layout 才能對全部的view判斷出位置以及尺寸。

Got enough constraints

圖庫實例

如今你應該對constraint是什麼以及知道如何在不一樣view之間創建關係來構造你的佈局。 接下來,你將會看到如何使用 Auto Layout 以及 constraints 來創造一個符合現實世界場景的佈局。

假設你要製做一個關於你最喜歡的程序員的圖庫應用,在景觀和肖像方向,它看上去應該以下圖所示:

The Gallery app

這個屏幕如今被分紅了4塊大小相同的部分。每一個部分有個imageview以及一個label。你怎麼樣來作到這個呢?

讓咱們從新開始這個程序。你可使用你現存的「constraints」項目經過把裏面的按鈕所有刪光。

或者,你能夠從新建立一個新項目,用 Single View Application 模板而後你隨便給他取一個名字你喜歡的名字。好比說,「畫廊」。這裏面只須要使用nib文件,因此請禁用掉storyboards 選項。

從對象庫打開ViewController.xib文件, 把一個普通的view放到canvas上。把它的寬設爲160 points,高設爲230 points, 而後把背景改成你喜歡的某種顏色 (我把它改成綠色):View with auto layout

這個view在它的空間內有4個constraint。不像一個button或者label,一個普通的UIView 沒有固有內容尺寸功能。因此它必需要有足夠的constraints來斷定它的位置以及大小,因此如今這個view須要constraints來決定它須要的尺寸大小。

你可能想知道,這些尺寸的constraints在哪裏?在這種狀況下,這些view的尺寸經過他們superview的尺寸來獲得。在這個佈局中,有兩個Horizontal Spaces 以及兩個Vertical Spaces,而且這些都有固定尺寸。你能夠在文檔概要圖中看到這些:

Constraints for UIView in document outline

綠色view的寬度能夠經過這個公式 「superview的寬度 減去(109 + 51)」 來計算獲得,相似的它的高度能夠經過 「superview的高度 減去(153 + 77)」。 由於這些空白constraints被固定了,全部view自己沒有機會來改變大小。但當你轉動應用時,superview的尺寸從320×460變爲480×300。把這新的寬度以及高度放到公式中,你會獲得一個新的綠色view的尺寸。

你能夠經過運行程序而且轉動至景觀模式看到這個現象,但你也能夠直接在 Interface Builder裏直接模擬這種狀況。

選擇nib文件裏最頂層的view 而後到 Attributes inspector裏去看,在 Simulated Metrics 部分裏, 把方向改成景觀模式:

Simulated metrics landscape

這裏能夠看到 nib 文件在景觀方向的直接佈局現實。這個綠色view爲了要知足 Horizontal and Vertical Space constraints 而從新改變了它的尺寸。

再切回到肖像方向。

提示:如今有兩個理由解釋在nib文件上你爲何要用一個普通的UIView : a) 你將要用它來作其餘view的容器,使用它能夠幫助你組織你nib文件的內容。; b) 這對於一個定製的view或者control來講是一個佔位標誌,你能夠把它類屬性設置爲你本身寫的 UIView或者 UIControl的子類。

有時當設備轉動時你不是總但願你的UIView 從新改變大小, 因此如今咱們經過 constraints 來定製view的固定寬度/或者高度。咱們來動手作一下。 選中綠色view而後在 Pin 菜單, 選擇Width。一樣地再次選中綠色view而後在菜單裏選擇 PinHeight。

你如今能夠對view添加兩個新的constraint,一個160 point的Width constraint 和一個230 point Height constraint:

Width and height constraints on UIView

由於寬度和高度只適用於這個view,在文檔概要圖中,他們處在view自身的目錄下。一般來講,cnostraints只表現爲兩個view之間的關係 – 好比說,在綠色view和它的灰色superview之間有 Horizontal 和 Vertical Space constraints 這個關係 – 但你也能夠認爲 Width 和Height constraints 是view和它自身的關係。

如今運行程序。恩!在肖像方向看上去不錯。 如今把view翻轉至景觀方向。擦! 它的樣子不只不是你想要的 – 它自身的尺寸又改變了 – 並且Xcode也報了一個使人討厭的錯誤信息:

Gallery[68932:11303] Unable to simultaneously satisfy constraints.  Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) ( "", "", "", "", "" ) Will attempt to recover by breaking constraint    Break on objc_exception_throw to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

是否還記得我說過對於view來講必需要有足夠多的constraint,那麼Auto Layout才能計算出全部view的位置以及尺寸?那麼,如今這個例子的狀況是它有太多的constraints了。不管什麼時候當你獲得錯誤 「Unable to simultaneously satisfy constraints」時, 這在暗示你的constraints在某些地方起衝突了。

讓咱們再來看看那些contraints:

Conflicting constraints

對於這個綠色view,目前有6個constraint。四個以前你見過,另外兩個新的 Width 和Height 是你剛加上去的。那麼衝突起在哪裏呢?

那麼, 在肖像模式中數學的計算是沒有問題的。superveiw的尺寸是320 points。若是你把綠色view的寬度再加上Horizontal Space的長度,那麼你應該獲得320這個值。我定位綠色view的方式是:51 + 160 + 109 = 320。相似地,垂直vertical constraints 應該加到 460。

但當你轉到設備至景觀模式時,主窗口 (也就是它的superview)是 480 points 寬。這意味着 51 + 160 + 109 + ? = 480。 在這等號的左邊還須要一個160 points可是Auto Layout殊不知道去哪裏獲得它。相似地,垂直座標也是這個狀況。

如今咱們遇到的衝突爲如下兩種狀況中的一種,要麼view的寬度是固定的可是它對應的頁邊必須是能夠改變大小,要麼它對應的頁邊是固定的可是它的寬度能夠改變大小。 在上面的例子中,你想要這個view在兩個方向保持相同的寬度,因此後面的Horizontal Space 必需要刪除掉。

把右邊的 Horizontal Space刪除以及把底部的Vertical Space刪除。如今 nib 文件應該看上去這樣了:

Conflicting constraints fixed

如今這個view已經有恰當數量的constraint來決定它的尺寸以及位置。很少也很多。再次運行程序,能夠看到xcode報錯信息已經沒有了,這個view也在屏幕轉動後保持了相同尺寸。

提示: 儘管 Interface Builder 已經很努力的幫你避免掉無效的佈局了,可是它不是萬能的。 但是至少Auto Layout會爲你報出一個詳細的錯誤信息當你有些設置是錯誤的時候。 在 iOS 6 by Tutorials這本書裏的」Intermediate Auto Layout」你能夠學到更多關於如何分析錯誤信息以及如何診斷佈局問題的介紹。

把肖像畫出來

在綠色view中拖進一個label。 注意如今的guides是在綠色view中出現了,由於它是label的superview。

Drag label into green view

根據guides把label放到綠色view的左上角。這會給label在綠色view中添加兩個 Space constraints 來定位本身:

Label constraints

注意這兩個新的 Horizontal and Vertical Space constraints 是被列在綠色view的contraints目錄下面而不是main view下。

如今稍微把綠色view移動一點。你能夠看到只有在綠色view和它的superview之間constraints改變了。而不是label的那些。 這個label會根據綠色view一直待在同一個相同的地方。

選中label而後把它移動到綠色view的底部邊緣,並使它中心對稱。而後在nib裏拖進去一個新的imageview,使佈局看上去以下圖所示:

Image view in gallery

把這imageview固定在頂部,以及它superview的左右兩個邊界。但它的底部是經過一個標準spacing與底部標籤相連。

下載 這份教程的素材 而後解壓文件。在裏面你會找到一個 Images 文件夾 – 把它加入到你的項目中去。設置 Ray.png 做爲你imageview的image, 而後把 image view的模式改成Aspect Fit而且設置它的背景顏色爲白色。接着把label的text寫爲「ray」。

你的佈局如今看上去應該是這樣的了:
Gallery with Ray

請注意如今Interface Builder 已經在label上設置一個 Height constraint了。這發生在你爲你的image view設置image的時候。

Label fixed height

Interface Builder已經嘗試在避免某種含糊的佈局的狀況發生。若是image view或者label都沒有一個固定高度的話,那麼Auto Layout是不知道如何從新設定他們的高度的當綠色view變化時。(對於如今而言Interface Builder彷佛會忽略設置在綠色view上面的固定Height constraint)。

讓咱們來假設在某種狀況下你app裏的綠色view變高了100 points。那麼如今這多出來的100 points在imageview和label當中是如何分配的呢?是否是imageview也變高了100 points而label保持原樣呢?或者說是label變高了而imageview保持原樣?或者說他們是對半分的,25/75分,46開?,或者其餘某種分法?

Auto Layout是不會作這些假設的,全部只有Interface Builder來經過給定label一個固定尺寸「幫助」咱們解決這問題。固然它也能夠給imageview一個固定尺寸,可是給label是更有意義的。

對於此刻來講, 讓咱們姑且先使用label上面的Height constraint。

提示: 對小布局設計來講一個比較恰當的解決方法是改變label的「Content Compression Resistance Priority」。這點你之後會學到。若是你等不及了想使用的話,那麼請直接到label的Size inspector for the label而後設置vertical Content Compression Resistance Priority到751。能夠到看到label上的 Height constraint會消失掉的。

 

加入其餘頭像

把綠色view移動到main view的左上角,是否還記得綠色view的Horizontal Space 以及 Vertical Space constraints 斷定了它在superview中的位置。依然仍是那些constraints,可是他們如今的值被設爲了0 - 藍色線條的就是他們(有白色邊界的) 在window的左上角:

View in top-left corner
雖然這個view是徹底在角落裏的,但它仍是須要constraints來把它定位在那裏。就把他們想象成邊緣值爲0吧。

選中綠色view而後按 Cmd-D 複製。把複製品移到右上角去:

Green view in top-right corner

再分別複製他們把他們移動左下角以及右下角。

把屏幕設計成以下所示:

Gallery design

這幾位是比較帥的程序員 :-)

運行程序,能夠看到肖像方向,界面看上去還不錯,可是在景觀方向就不盡如人意了:

Gallery looks bad in landscape

這應該很明顯能夠看出錯在哪裏了: 你已經對4個view容器設置了固定的寬和高,因此他們會一直保持這那些尺寸,不管它的superview的尺寸如何變化。

選中4個view裏面的 Width (160) and Height (230) constraints 而後刪除他們。如今運行程序試試,你會獲得下圖所示,仍是不盡如人意:

Still looks bad in landscape

這個問題看上去有點像咱們以前在介紹裏面解決過的問題,因此讓咱們回想一下當時是如何解決的,你應該記得咱們是給view設置相同的寬和高來解決的。

選中全部4個view而後作 PinWidths Equally操做。再次從新選中而後再作PinHeights Equally操做。

再次運行程序而且把之轉到景觀方向。嗯….它仍是和以前的同樣嘛。這是爲何呢?

好吧,若是你仔細觀察上面的截圖,你會發現其實每一個view確實都有相同的高度,而且他們的寬度彷佛也相同(只不過綠色的和棕色被黃色和藍色部分遮蓋住了),因此咱們的contraints是對的,是的被知足的。如今的問題僅僅是寬度和高度不是你想要的。若是這是這樣,那麼確定還有其餘constraints在其中起做用了。

100%確定,若是你仔細看這些view的constraints,你會看到他們一樣的有Horizontal 以及 Vertical Space constraints來強迫他們定位本身的位置。 (請看main view的constraints,而不是4個子view的):

Bad H-space

更加悲劇的是,你都不能刪除這些 constraint,main view的T型狀對象不是藍色粗體,因此能夠推斷出 Interface Builder 把他們放在那裏是爲了不某種佈局問題的。

它爲何要這麼作呢? 目前只能這麼解釋,全部的4個view都必須擁有相同的尺寸大小是不足以決定他們確切的的尺寸應該是多少的,由於Auto Layout是不知道他們幾個是如何鏈接在一塊兒的。在咱們設計上,他們是邊和邊的鏈接在一塊兒,可是他們以前卻沒有這種constraints。因此Auto Layout不會知道它須要把「Ray」 and 「Matthijs」 塊寬度上須要分開。

若是Auto Layout不能經過自身才推斷出這層意思的話,那你就只能本身來告訴他了。

To be related

選中 Ray 和 Matthijs 塊而後選擇 PinHorizontal Spacing操做。由於這些塊是邊與邊相連的,因此在他們之間須要添加一個尺寸爲0的Horizontal Space constraint,有了這個, Auto Layout 就知道他們是如何關係的了。

重要提示: Interface Builder不會自動幫你刪除黃色view和superview之間的主導Horizontal Space限制(就是上一張截圖所示的),但它會將它升級爲一個user constraint(比較粗的T狀對象)。 你如今能夠把它刪了。若是你不刪的話,你會獲得一個「Unable to simultaneously satisfy constraints」的錯誤當你把應用轉至景觀方向時。

運行程序,看看如今是什麼效果了:

Landscape a bit better

這個看上稍微好一點了。如今四個view是相同寬度,但高度仍是不對的。解決方案和以前的相似:在Ray和Dennis Ritchie之間放一個 Vertical Space而後把Dennis的view和window頂部之間的Vertical Space刪除。

再次運行程序,如今看上去應該是這樣了:

Gallery landscape OK

請注意「Dennis Ritchie」 label並不在它imageview的下方正中心。這件事最開始發生在當我想要在label裏輸入文字的時候。這個label初始化時是放在view的中間的,但Interface Builder仍是以爲把這個中心constraint替代爲一個Horizontal Space效果會更好。若是你也有這個問題,那麼請選中這個label而後進行AlignHorizontal Center in Container操做來修復它。

請再次注意下這些imageview:他們是延伸出來的,由於你沒有給他們設置一個固定尺寸。你可能還不知道這一點,但設置他們確實是你的義務。:) 在景觀方向下,這些view是不會自動修復的。可是,若是你想要一個imageview保持它原來的比例的話,那你就不是那麼走運了。若是你不使用Interface Builder來作一點修改的話,你是不可能獲得下圖的效果的:

Aspect ratio on images

不幸的是, Interface Builder目前不提供一些能保持view原始比例的constraints。要作那個效果,你須要經過代碼本身建立以及設置constraints。在iOS 6 by Tutorials裏面有一章」Intermediate Auto Layout」是介紹具體怎麼作的。

小貼士:你以前可能已經知道了你能夠經過在Simulated Metrics來設置方向以便於你預覽用戶界面。你也能夠直接Interface Builder裏面測試各類view的縮放行爲。

選中main view,在Simulated Metrics下,把尺寸設置爲Freedom。如今你能nib文件添加縮放處理,你能夠把它設置成你想要的任何型狀。順便也請放心,Auto Layout會立刻從新爲你計算出新的佈局的:

Freeform

而後,你也要對此警戒。由於有時候當你從新設置尺寸時 Interface Builder 會給它本身添加新的constraints。就像如今這兒的右下角有一個新的Horizontal Space同樣。固然這也可能會刪除現有的constraints,當你把nib文件放大出它原來的bounds的時候。

接下來去哪?

若是你從頭看到這裏了,那麼恭喜!- 你如今已經知道了關於Auto Layout的全部事情,而且已經對基礎知識作了實踐!可是在這方面仍是有許多須要你去學習…

如今這份教程也就是你剛讀的只是 iOS 6 by Tutorials 這本書裏 Beginning Auto Layout chapter章節的前半部分。後半部分會教到如何使用 Auto Layout來建立更多 「現實世界」的屏幕布局,以及有關同時使用Auto Layout 和Interface Builder 的全部技巧。

和其餘視覺設計工具同樣, Interface Builder 有它本身的限制可是有時候若是它和 NSLayoutConstraint對象一塊兒使用的話是會效果更好。 iOS 6教程書對於這個主題投入了一整個的章節- Intermediate Auto Layout.。因此若是你想要對此刨根問底的話, 那就買書看吧

相關文章
相關標籤/搜索