天天看點

iOS Auto Layout 1

轉自:http://www.cocoachina.com/industry/20131203/7462.html

你是否曾經想讓你的app在橫豎屏方向上看起來都表現良好而受挫?是否在做支援iPhone和iPad螢幕布局界面時幾近大小便失禁?今天我将給你帶來好消息!   一直為大小相同的螢幕設計一個使用者界面并不難,但如果螢幕的尺寸改變的話,UI元素的位置和大小也需要相應的做出改變。   到目前為止,如果你的設計相當的複雜,那麼你必須編寫大量的代碼來适應這樣的布局。你應該很高興,現在這樣的情況再也不存在了--iOS6為iPhone和iPad帶來了一個極好的新特性:自動布局。Xcode 5和 iOS7中對自動布局做出了改善!如果你曾經嘗試着在Xcode4中使用自動布局并最終做出放棄,現在是該給Xcode5一次機會了。   在你的程式中,自動布局不僅可以很容易的支援不同大小的螢幕,一個額外的功能,它也使得本地化幾乎變得微不足道。你不再需要為每種你希望支援的語言建立新的nibs或storyboards,包括像Hebrew或Arabic這樣從右到左的語言。   這個教程将向你展示如何使用Interface Builder開始自動布局.在 iOS6 教程中,我們進一步讨論過這個教程,然後有一個基于這個知識點完整的新章節,并且向你展示如何通過代碼完全釋放出自動布局的能量。   注意:我們已經開始将iOS6教程中相應的章節更新到iOS7-這隻是先給大家解解饞!當我們完成後,所有iOS6 PDF教程的訂閱者将會得到免費的更新下載下傳。   so,備好零食和你喜歡的咖啡,準備成為自動布局的達人吧!   springs和struts的問題 你肯定很熟悉autosizing masks-也被認為是springs&struts模式。autosizing mask決定了當一個視圖的父視圖大小改變時,其自身需要做出什麼改變。它有一個靈活的或固定不變的margins(struts)嗎?它的寬和高要做出什麼改變(springs)?   舉個例子,一個寬度靈活的視圖,如果其父視圖邊框,那麼它也會相應的變寬。一個視圖右邊擁有固定的margin,那麼它的右邊緣将會一直粘住其父視圖的右邊緣。   autosizing系統在簡單的情況下非常奏效,但當你布局變得更複雜時,它立馬跪了。讓我們看一個springs和struts不能處理的示例。   打開Xcode5,建立一個基于Single View Application模闆的iPhone項目。叫做"StrutsProblem":

iOS Auto Layout 1

點選Main.storyboard。在你做别的之前,首先将這個storyboard的自動布局關了。你需要在File inspector,第一個選項的第六個tabs裡:

iOS Auto Layout 1

  将Use Autolayout的box勾選去掉。現在storyboard使用舊的struts-and-springs模型。   注意:任何你使用Xcode4.5或更高版本中,nib或者storyboard檔案都預設激活了自動布局。因為自動布局是iOS6以及以上系統的一個新特性,如果你想使用最新的Xcode開發相容iOS5的程式,你需要将這個選項去掉。   拖拽三個新的視圖到主視圖上,并且像這樣排列起來:

iOS Auto Layout 1

為了表述更清楚,這裡給出每個視圖的顔色,這樣你就能厘清哪個是驢子哪個是馬了。 每個視圖的inset到視窗的距離都是20點;視圖之間的距離也是20點。底部的視圖的寬是280點,上面兩個視圖的寬都是130點。所有的視圖的高都是254。     在iPhone Retina 4-inch simulator上運作這個程式,并且将模拟器旋轉到landscape。程式看起來便變成這副鬼樣,這不是我想象的那樣:

iOS Auto Layout 1

注意:你可以使用Hardware\Rotate Left和Rotate Right菜單選項旋轉模拟器,或者通過按下鍵盤上的 ?   鍵,同時按下←或→。   而你想象的程式在landscape應該像這樣:

iOS Auto Layout 1

  很明顯,三個視圖的autosizing masks留下了一些需要改進的地方。将左上方視圖的autosizing設定改成這樣:

iOS Auto Layout 1

這将會讓視圖貼附左上邊緣(不是右下邊緣),并且當父視圖大小改變時,重新調整自身水準和垂直方向的大小。   同樣的,右上方視圖的autosizing設定改成這樣:

iOS Auto Layout 1

底部視圖:

iOS Auto Layout 1

再次運作程式,并且旋轉到landscape。現在看起來像這樣:

iOS Auto Layout 1

已經很接近了,但又不完全一樣。視圖之間的padding不正确。換個說法就是視圖的大小不完全正确。問題出在當父視圖改變大小時,autosizing masks告訴子視圖調整大小,但又沒告訴子視圖該調整多少(坑兒?)。   你可以調戲autosizing masks-比如,改變靈活寬度和高度設定(springs)-你不會得到完全正确的三個間距20點的視圖。

iOS Auto Layout 1

為了解決這個springs和struts方法的布局問題,非常不幸,你需要額外寫一些代碼。   在旋轉使用者界面之前、之間、之後,UIKit會發送一些消息到你的視圖控制器,你可以截獲這些消息,進而對你UI做出改變。代表性的像viewWillLayoutSubviews,你會重寫這個方法進而改變任何需要重新排列的視圖的frame。   在這之前,你需要先做出一個outlet屬性來引用這個視圖。   切換到Assistant Editor模式,按住Ctrl,将三個視圖都拖到ViewController.m中去:

iOS Auto Layout 1

  分别連結視圖到這三個屬性:

  1. @property (weak, nonatomic) IBOutlet UIView *topLeftView; 
  2. @property (weak, nonatomic) IBOutlet UIView *topRightView; 
  3. @property (weak, nonatomic) IBOutlet UIView *bottomView; 

  下面的代碼寫到ViewController.m:

  1. - (void)viewWillLayoutSubviews 
  2.     if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) 
  3.     { 
  4.         CGRect rect = self.topLeftView.frame; 
  5.         rect.size.width = 254; 
  6.         rect.size.height = 130; 
  7.         self.topLeftView.frame = rect; 
  8.         rect = self.topRightView.frame; 
  9.         rect.origin.x = 294; 
  10.         rect.size.width = 254; 
  11.         rect.size.height = 130; 
  12.         self.topRightView.frame = rect; 
  13.         rect = self.bottomView.frame; 
  14.         rect.origin.y = 170; 
  15.         rect.size.width = 528; 
  16.         rect.size.height = 130; 
  17.         self.bottomView.frame = rect; 
  18.     } 
  19.     else 
  20.     { 
  21.         CGRect rect = self.topLeftView.frame; 
  22.         rect.size.width = 130; 
  23.         rect.size.height = 254; 
  24.         self.topLeftView.frame = rect; 
  25.         rect = self.topRightView.frame; 
  26.         rect.origin.x = 170; 
  27.         rect.size.width = 130; 
  28.         rect.size.height = 254; 
  29.         self.topRightView.frame = rect; 
  30.         rect = self.bottomView.frame; 
  31.         rect.origin.y = 295; 
  32.         rect.size.width = 280; 
  33.         rect.size.height = 254; 
  34.         self.bottomView.frame = rect; 
  35.     } 

當視圖控制器旋轉到一個新的方向,這個回調将會被調用。它會監控視圖控制器旋轉的方向,并且适當的調整視圖大小-在這種情況,根據已知iPhone螢幕大小會有一個hard-code(将可變變量用一個固定值來代替的方法叫做hard-code)偏移。這個回調會在一個動畫block中發生,是以會動态的改變大小。   暫時還不要運作這個程式。首先你需要按下面的樣子重新儲存三個視圖的autosizing masks,否則autosizing mechanism将會和你在viewWillLayoutSubviews中設定的位置和大小沖突。

iOS Auto Layout 1

這樣就可以了,運作程式并且翻轉到landscape。現在視圖排列的非常号。翻轉回到portrait,經核實,一切都良好。   這樣奏效了,但是你需要為這個非常簡單的例子編寫大量的布局代碼。想象一下,為布局付出的努力是非常複雜的,特别是個别視圖動态的改變大小,或者子視圖的個數是不固定的。   現在試着在3.5寸的模拟器上運作程式。我了個去。視圖的位置和大小又錯了,因為viewWillLayoutSubviews的hard-code坐标是基于4英寸大小的手機(320x568取代320x480)。你可以增加另一個if語句判斷螢幕大小,并使用不同的坐标集,但是你可以看到這個方法很快變得不切實際。

iOS Auto Layout 1

注意:另一個你可以采取的方法就是為portrait和landscape模式建立獨立的nibs。當裝置旋轉時,你從另一個nib中裝載視圖并替換掉目前的那個。但這任然需要做很多工作,并且維護兩個nibs也會增加問題。當你使用storyboards替代nibs的時候,這個方法也變得不切實際。   自動布局拯救猿! 現在你将會看到如何用自動布局實作相同的效果,從ViewController.m中移除viewWillLayoutSubviews,因為我們不再需要寫任何代碼。   選擇Main.storyboard,并在File inspector中選擇開啟Use Autolayout:

iOS Auto Layout 1

運作程式,旋轉到landscape。現在看起來像這樣:

iOS Auto Layout 1

讓我們把自動布局付諸行動。當你點選頂部兩個視圖時,按住?鍵,這樣兩個視圖都被選中了。從Xcode的Editor菜單中選擇Pin\Widths Equally:

iOS Auto Layout 1

再次選中兩個相同的視圖,選擇Editor\Pin\Horizontal Spacing。(盡管你執行完第一次Pin處理後,兩個視圖看起來還是被選中的,但其實他們隻是在一個特别的布局關系顯示模型裡。是以你需要重新選擇這兩個視圖)   storyboard現在看起來像這樣:

iOS Auto Layout 1

橙色的"T-bar"形狀代表視圖間的限制。目前為止你增加了兩個限制:一個等寬限制和一個位于兩個視圖間的水準限制。限制表達了視圖之間的關系,并且他們是你使用自動布局建立布局最主要的工具。這貨看起來有點吓人,但是一旦弄懂它的意思,便變得相當簡單。   為了繼續為這個螢幕履歷布局,執行下面這些步驟。每個步驟增加更多橘黃色的T-bars.   o Top Space to Superview o Leading Space to Superview For the view on the right, choose: o Top Space to Superview o Trailing Space to Superview And for the big view at the bottom: o Leading Space to Superview o Trailing Space to Superview o Bottom Space to Superview   現在你應該有了下面這些限制:

iOS Auto Layout 1

注意T-bars仍然是橘黃色的。這意味這你的布局沒有完成;自動布局沒有足夠的限制條件計算出視圖的位置和大小。解決辦法便是增加更多限制,直到他們變藍。   按下 ?  鍵并選中三個視圖。從Editor菜單中,選擇Pin\Heights Equally。   現在選中左上角的視圖和底部視圖(像前面一樣按住 ? 鍵),選擇Editor\Pin\Vertical Spacing.   Interface Builder看起來應該像這樣:

iOS Auto Layout 1

T-bars已經變藍了。自動布局現在已經有足夠的資訊來計算出一個有效的布局。這看起來有點雜亂無章,這是因為等寬和等高限制條件占去了很大空間。   運作程式并且...我說吧,不需要寫一行代碼便運作的很好了。不管你在哪個模拟器上運作;在3.5英寸和4英寸裝置上,布局都運作良好。

iOS Auto Layout 1

這非常酷,但是究竟你在這做了什麼?自動布局讓你表達出布局中的視圖和其他每個視圖的關系,而不是需要你指出視圖有多大,放在哪兒。你需要放置以下這些關系(即我們所謂的限制)到布局中: 1.左上角和右上角的視圖總是有相等的寬度(也就是pin中第一個widths equally指令)。 2.左上角和右上角的視圖水準方向有20點距離(也就是pin中的horizontal spacing)。 3.所有的視圖總是有相同的高度(也就是pin中heights equally指令)。 4.上面兩個視圖和下面那個視圖垂直方向上有20點距離(也就是pin中的vertical spacing)。 5.視圖和螢幕邊緣有20點空間(top,bottom,leading和trailing space相對于父視圖的限制)。   這些就足以表達出自動布局該怎麼放置視圖,以及當螢幕大小改變時該如何處理。

iOS Auto Layout 1

你可以在左邊Document Outline中看到你所有的限制,組名叫做Constraints(當你為storyboard激活自動布局時才會加進來)。   如果你在Document Outline中點選一個限制,Interface Builder将會在視圖中高亮出它:

iOS Auto Layout 1

  限制是一個真實的對象(NSLayoutConstraint),并且他們也有屬性。比如,選擇上面兩個視圖的間距限制條件(叫做"Horizontal Space(20)"),然後切換到Attributes inspector。你可以在那裡通過編輯Constant字段改變邊緣空間的大小。

iOS Auto Layout 1

将它設定為100,然後再次運作程式。現在他們邊緣空間變得更寬了:

iOS Auto Layout 1

自動布局在描述視圖上比springs和struts顯得更有表現力。在這篇教程的剩餘部分,你将會學到限制的一切,以及如何将他們應用到Interface Builder上來構造出不同種類的布局。   自動布局如何工作 正如你在上面測試樣例中所看到的一樣,自動布局最基本的工具是限制。一個限制描述了兩個視圖間的幾何關系。比如,你可能有這樣一個限制: "label A右邊緣和button B左邊緣有20點的空白空間。"   自動布局會考慮到所有的限制,然後為你的視圖計算出理想的位置和大小。你再也不需要親自為你的視圖設定frames了-自動布局會完全基于你為這些視圖設定的限制為你做這個工作。   自動布局以前,你一直需要為視圖的frames設定hard-code,要麼在Interface Builder中将他們放置在特定的坐标,或通過傳遞一個rectangle到initWithFrame:,或者設定視圖的frame,bounds或者center屬性。   就你剛剛做的那個程式,你需要明确設定frames為:

iOS Auto Layout 1

還需要為這些視圖設定自動調整大小的masks:

iOS Auto Layout 1

  這再也不是你需要為螢幕設計所考慮的東西了。使用自動布局,你需要做這些:

iOS Auto Layout 1

視圖的大小和位置再也不重要了,隻有限制要緊。當然,當你拖一個建立的button或label到畫布上時,它會有一定的大小,并且你會将它拖到某一位置,但這是隻一個用來告訴Interface Builder如何放置限制的設計工具。     想你所想,如你所願 使用限制最大的優勢就是你再也不需要把時間浪費在坐标上了。相反,你可以向自動布局描述視圖如何和其他視圖相關聯,自動布局将會為你完成所有困難的工作。這叫做根據目的設計(designing by intent)。   當你根據目的設計時,你表達的是你想要實作什麼,而不需要關心它如何實作。"button的左上角坐标為(20,230)",現在你可以這麼說了:button是垂直居中于它的父視圖,并且相對于父視圖的左邊緣有一個固定的距離。   使用這個描述,不管父視圖多大或多小,自動布局都可以自動計算出你的button需要在哪兒出現,   其他根據目的設計的示例(自動布局可以處理所有這些指令): "這兩個text fields的大小需要一直相等。" "這兩個button需要一直一起移動。" "這四個labels需要一直右對齊。"   這使得你使用者界面的設定更具描述性。你隻需簡單的定義限制,系統會為你自動計算frames。   在第一部分你看到,即使為幾個視圖在橫豎方向上正确的布局都需要做大量的工作。有了自動布局,你可以繞過這些麻煩。如果你正确的設定了限制,那麼在橫豎屏方向上,布局将不需要做任何改變。   使用自動布局另一個重要的好處就是本地化。比如德語中的文本,出了名的比老奶奶的裹腳布還要長,适配起來是一件很麻煩的事。再次,自動布局拯救了猿,因為它能根據label需要顯示的内容自動改變label的大小。   現在增加德語,法語或者其他任何一種語言,都隻是設定限制的事,然後翻譯文本,然後。。。就沒有然後了!

iOS Auto Layout 1

獲得自動布局竅門最好的方法就是使用它,是以這正是剩下教程中你會學到的東西。   注意:自動布局不僅對旋轉有作用;它還能輕易的縮放你UI的大小進而适應不同尺寸的螢幕。這并不是巧合,當iPhone5擁有更高螢幕的同時,這個技術也同時加到了iOS中!自動布局能輕易的拉伸你程式的使用者界面,進而充滿iPhone5垂直方向上多出來的空間。随着iOS7中的動态類型,自動布局變得更加重要了。使用者現在可以改變全局字型大小設定--有了自動布局,這将變得非常簡單。     擁抱限制(courting constraints) 關閉你目前的項目并用Single View Application模闆建立一個新的iPhone項目。叫做"Constraints"。任何用Xcode5建立出來的項目都會自動假定你會使用自動布局,是以你并不需要額外做任何事情。   點選Main.storyboard打開Interface Builder。拖一個新的Button到畫布上。注意當你拖拽的時候,藍色虛線将會出現。這寫線用來做向導。

iOS Auto Layout 1

在螢幕邊緣以及中心的時候,都會有向導線:

iOS Auto Layout 1

  如果之前你已經使用過Interface Builder,那麼你肯定看到過這些向導線。這對我們對齊控件有很大的幫助。   在Xcode4中激活自動布局時,向導線有另外一個目的。你任然可以用他們來對齊,但是他們也會告訴你新的限制将會在哪兒。如果你将button沿着向導線反方向拖拽到左上角時,Xcode4中的storyboard看起來便像這樣:

iOS Auto Layout 1

有兩個藍色的東西附屬在button上面。這些T-bar形狀的對象便是限制了。Xcode 4的Interface Builder中不管你将UI控制器放在哪兒,它總是會給出有效的限制。理論上這聽起來是個好主意,但是實踐起來,在Interface Builder中使用自動布局卻非常困難。   幸運的是,Xcode5中已經有所好轉。将button拖拽到畫布上之後并看不到T-bars形狀的東西:

iOS Auto Layout 1

  同時在Document Outline面闆中也沒用Constraints部分。得到結論:此時button上并沒有設定任何限制。   那這是如何運作的呢?我們之前了解的自動布局總是需要足夠多的限制才能決定視圖的大小和位置,但是現在我們這兒跟本沒有限制。确定這是一個完整的布局?   這這是Xcode5相對Xcode4來說最大的一個提升:再也不強制你總是有一個有效的布局。   注意:1.運作一個無效布局的程式是不明智的,因為自動布局不能正确的計算需要将視圖放在哪兒。要麼視圖的位置是不可預知的(限制不夠),要麼程式将會崩潰(限制過多)。   2.Xcode4設法保證總是有足夠多正确的限制來建立一個有效的布局。不幸的是,它經常會将你的限制替換為你并不想要的。這會令人很沮喪,正是因為這個原因很多開發者放棄了自動布局。   3.Xcode5中,當你編輯Storyboard時它允許你有不完整的布局,但它也會指出哪些地方你還需要修改。使用Interface Builder建立的自動布局驅動使用者界面變得更有趣了,使用Xcode5也消耗更少的時間。   如果你根本不提供任何限制,Xcode自動配置設定一套預設的限制,正是我們所知的自動限制。它會在程式built的編譯時間中去完成這些事,而不是設計時間。當你設計你的使用者界面時,Xcode5中的自動布局為了不參與你的設計方法而努力工作,這這是我們喜歡它的原因。   自動限制為你的視圖提供一個固定尺寸和位置。換句話說,視圖總是擁有跟你在storyboard中看到的一樣的坐标。這是非常友善的,因為這就意味着你可以大量的忽視自動布局。你可以為那些擁有充分限制的控件不增加限制,隻為那些需要特殊規則的視圖建立限制。   OK,讓我們玩一玩限制并看看他們能做什麼。現在,按鈕是在左上角,并且沒有限制。确認按鈕跟兩個拐角向導線對齊。   使用Editor\Pin菜單為按鈕增加兩個新的限制,看起來像這樣:

iOS Auto Layout 1

這是Leading Space to Superview和Top Space to Superview選項。   所有的限制都會在Document Outline面闆中列出來:

iOS Auto Layout 1

目前有兩個限制,一個是button和main view左邊緣的Horizontal Space限制,一個是button和main view上邊緣的Vertical Space限制。這個關系通過限制描述起來便是:"button總是位于其父視圖左上角20點處。"   注意:這些其實都不是非常有用的限制,因為他們有相同的自動限制。如果你總是想你的button相對于父視圖左上角,那麼你還不如不提供任何限制,讓Xcode為你做這些。   現在拖動button并将它放到螢幕的右上角,再次和藍色向導線對齊:

iOS Auto Layout 1

哇哦,這裡發生了什麼?在Xcode4中這會破壞舊的限制并指派一個基于藍色向導線的新限制,但是在Xcode5中button保留了現存的限制。但問題是button在Interface Builder中的大小和位置再也不和自動布局希望基于限制的大小和位置相符合了。這叫做錯位的視圖。(misplaced view)   運作程式。Button仍然會出現在螢幕的左上角:

iOS Auto Layout 1

  當談到自動布局,橙色代表壞的。Interface Builder繪制兩個橙色方塊:一個是虛線邊框,一個是實線邊框。虛線方塊是根據自動布局顯示視圖的frame。實線方塊是根據你在螢幕上放置的視圖的frame。這兩個應該吻合的,但是這裡并沒有。   如何修改取決于你想要達到什麼目的: 1.你想讓button附屬于螢幕左邊緣254點處嗎?在這種情況下你需要将現存的Horizontal Space限制變大234點。這正是橙色badge中"+234"的意思。 2.你想讓button附屬于螢幕的右邊緣?那麼你需要移除現有的限制并重新建立一個新的。   删除Horizontal Space限制。首先在畫布或Document Outline中選中,然後按鍵盤上的Delete鍵。

iOS Auto Layout 1

注意這次Vertical Space限制變橙色了。直到現在它都是藍色的。那一個限制并沒有任何錯誤;它的意思是剩下的沒有足夠的限制決定button完整的位置。你任然需要在X軸方向增加一個限制。   Note:你可能會奇怪,為什麼Xcode不為X軸方向自動增加一個限制。Xcode中的規則是:Xcode隻為那些你沒有設定任何限制的對象建立自動限制。一旦你增加一個限制,你便是告訴Xcode你接管了這個視圖。Xcode将不再增加任何自動限制,并希望你為這個視圖增加需要的限制。   選中button,并選擇Editor\Pin|Trailing Space to Superview.這迫使在button右邊緣和螢幕右邊緣增加一個新的限制。關系表達如下:"button總是位于距離其父視圖右上角20點處。"   運作程式并旋轉到landscape。注意button如何與螢幕右邊緣保持相同距離:

iOS Auto Layout 1

  當你放置一個對立于向導線的button(或者任何其他視圖)并建立一個限制時,你會得到一個根據"HIG"(Apple's iOS Human Interface Guidelines document)定義的标準大小的間隔限制。對于邊框來說,标準大小空間是20點。   現在将button向左拖拽一點:

iOS Auto Layout 1

由于視圖錯位,你得到了一個橙色虛線邊框。我們假設這個button新位置的确是你想要的。建立完一個限制後做一些細微的調整是很常見的,但這卻會導緻橙色方塊出現。一個修改方法就是移除限制并建立一個新的,但還有一個更簡單的解決方案。   Editor菜單上有一個Resolve Auto Layout Issues子菜單。從這個菜單中,選中Update Constraints。就我這個情況來說,這會告訴Interface Builder需要将限制變大64點,像這樣:

iOS Auto Layout 1

  很好,T-bars又變藍了,布局是有效的。在Document Outline中,你可以看到Horizontal Space限制不再有一個标準的間隔了:

iOS Auto Layout 1

到目前為止你已經嘗試過了Horizontal Space和Vertical Space限制。還有一個"center"限制。拖拽一個新的Button對象到畫布底部中心,根據向導線完好入位:

iOS Auto Layout 1

  為了保持button在水準方向上一直居中對齊于父視圖,你需要增加一個Center X Alignment限制。從Editor菜單選擇Align\Horizontal Center in Container.這會增加一個很長的橙色線段:  

iOS Auto Layout 1

  線之是以是橙色是因為你才僅僅指定了button的X軸,但Y軸并沒有指定限制。使用Editor\Pin菜單在button和視圖底部間增加一個Vertical Space限制。看起來像這樣:  

iOS Auto Layout 1

如果你不知道原因,這是Bottom Space to Superview選項。Vertical Space限制使button遠離視圖底部(再一次使用标準間隔)。   運作程式并旋轉到橫屏模式。甚至在橫屏模式,button也保持在螢幕底部的中心:

iOS Auto Layout 1

這就是你表達的意思---這個button始終應該位于底部中心。注意,你根本不需要告訴Interface Builder按鈕的坐标是什麼,除非你想将它固定在視圖上。     通過自動布局,你再也不需要擔心視圖位置的精确坐标或視圖大小了。相反,自動布局會根據你設定的限制得到這兩個參數。   你可以在button的Size inspector中看到這個經典轉移,現在有了很大的不同:

iOS Auto Layout 1

  如果不使用自動布局,輸入值到X,Y,Width或Height字段将會改變選中視圖的位置和大小。使用自動布局後,你仍然可以輸入新值到這些字段,但是如果你已經為視圖設定了限制,那這可能造成視圖錯位。你将不得不更新限制來比對新值。   舉個例子,把button的寬度改為100,畫布會變成這樣:

iOS Auto Layout 1

  Xcode4用Horizontal Space取代Center X Alignment限制,并且button上會産生一個新限制強制它的寬度為100 points。然而,Xcode5說,"如果你想讓button寬度變為100 points,對我來說無所謂,但是你要知道限制并不是這麼說的。"   在這種情況下你希望button是100點寬。對此有一個特殊的限制類型:Fixed Width限制。首先按一下Undo,這樣button又居中了,T-bars也變藍了。選中button并選擇Editor\Pin\Width。這會在button下面放置一個新T-bar:

iOS Auto Layout 1

  選中那個T-bar并在Attributes inspector中改變Constant為100.不管button的title多大或多小,這都會強制button的寬總是100點。為了能更好的看清你可以給button設定一個背景色:  

iOS Auto Layout 1

  你也可以在左邊的Document Outline中看到這個新的Width限制:

iOS Auto Layout 1

  與其他限制不同,在button和它的父視圖之間,Width限制隻會應用到button本身。你可以将這個認為是一個button本身和本身之間的限制。   你可能懷疑為什麼button之前沒有Width限制。自動布局是為何知道button有多寬?   事情是這樣的:button自己是知道自己有多寬。它根據自己的title text加上一些padding就行了。如果你為button設定一個背景圖檔,它也會考慮進去。   這正是我們熟悉的intrinsic content size。并不是所有的控制器都有這個,但大部分是(UILabel是一個例子)。如果一個視圖可以計算自己理想的大小,那麼你就不需要為它特别指定Width或Height限制了,你将會在稍後看到更多相關内容。

iOS Auto Layout 1

  為了恢複button到最佳大小,首先我們需要移除Width限制。然後選中button,并從Editor菜單中選擇Size to Fit Content。這樣就能夠恢複button的固有的内容尺寸了。   孤掌難鳴 向導線不但出現在一個視圖和它的父視圖之間,而且也會出現在相同層級的視圖之間。拖拽一個新的button到畫布上進行示範。如果你将這個button拖近其他對象,這時他們的向導線将會開始互相影響。   将新button放到之前一個button的後面完好入位:

iOS Auto Layout 1

  這還有一些向導虛線。Interface Builder識别出這兩個button可以通過不同方式對齊—頂部,中心以及基線。   Xcode4會将這些顯著的向導線轉變成新的限制。但是在Xcode5中,如果你想讓這兩個button間有限制,你需要自己建立。之前你已經使用過Editor\Pin菜單來建立這兩個視圖間的限制,但是還有一個更簡單的方式。   選中新的button并按住Ctrl拖拽到另一個button上,像這樣:

iOS Auto Layout 1

放開滑鼠按鍵,出現一個彈出框。選擇第一個選項,Horizontal Spacing。

iOS Auto Layout 1

這将會建立一個新的限制:  

iOS Auto Layout 1

  它是橙色的,這意味着這個button至少還需要另一個限制。button的大小是知道的(使用intrinsic content size),并且還有一個button在X軸上的限制。隻剩下Y軸沒有限制了。   這種缺失限制的情況是很容易确定的,但是更複雜的設計可能就沒這麼明顯了。幸運的是,你不再需要敏思苦想,Xcode已經記錄并可以确切的告訴你缺少了什麼。   在Document Outline中會有一個紅色的小箭頭,就在View Controller Scene後面。點選這個箭頭便會看到所有Auto Layout問題:

iOS Auto Layout 1

  我們将Y軸方向缺失的限制加進去。按住Ctrl并向下拖拽新的button:

iOS Auto Layout 1

這次彈出菜單有不同的選項了。這次菜單的選項是基于上下文環境的—你在哪些視圖間拖拽以及滑鼠移動的方向。選擇Bottom Space to Bottom Layout。   現在新button有一個位于螢幕底部的Vertical Space,也有一個跟其他button相關聯的Horizontal Space。雖然空間非常小(隻有8 points),T-bar可能不大容易看到,但它就在那裡。   點選Document Outline裡面的Horizontal Space(8):

iOS Auto Layout 1

  當你選中一個限制,它會高亮自己所屬的控制器。這個特别的限制位于兩個button之間。這個限制表達了:“不管第一個button在哪兒或多大,第二個button總是出現在第一個button的左邊”。   選中黃色背景的button并輸入較長的label,比如:“A longer label”。輸入完成後,button會為新的text改變大小,并且另一個button會移開。   最終,它依附在第一個button的左邊緣,這正是我們所期望的:

iOS Auto Layout 1

  為了更好的摸索這是如何工作的,多練一些吧。拖拽另一個button到畫布上并放到黃色button的上方,他們會垂直方向對齊到位(不要試着讓兩個button的左邊緣對齊):

iOS Auto Layout 1

  為新button設定一個綠色背景色,這樣就可以更容易看出它的範圍。   因為你将兩個button對齊在一起,現在他們之間存在HIG推薦的8 points間隔。按住Ctrl在兩個button之間拖拽将這變為一個限制。從彈出菜單中選中Vertical Spacing。   Note:“HIG”是“iOS Human Interface Guidelines”的簡稱,包含Apple推薦的良好的使用者界面設計。任何iOS開發者都有必要讀一讀這個規範。HIG解釋了哪些UI元素适合在什麼情況下使用,以及最佳使用方式。你可以在這裡找到。( https://developer.apple.com/library/ios/DOCUMENTATION/UserExperience/Conceptual/MobileHIG/Introduction/Introduction.html)   然而你并沒有被限制在controls間的标準間隔。限制是成熟的對象,就像視圖一樣,是以你可以改變它們的屬性。   選中兩個button之間的Vertical Space限制。你可以在畫布上點選T-bar,雖然這有點麻煩。目前最簡單的辦法就是在Document Outline裡面選擇限制。一旦你選中限制,再切換到Attributes inspector:

iOS Auto Layout 1

  在Constant字段裡輸入40改變限制大小。現在兩個button更進一步的分開了,但是他們任然是連接配接在一起的:

iOS Auto Layout 1

  運作程式并翻轉到landscape模式檢視效果:

iOS Auto Layout 1

  button必然會保持他們垂直方向的排列,但是水準方向就不了!原因很明顯:綠色button還沒有X軸方向的限制。   為綠色button增加一個到螢幕左邊緣的Horizontal Space并不能解決問題。這樣的限制隻會讓綠色按鈕總是保持在同一個X軸坐标,即便是在橫屏模式下。這看起來感覺不大對,是以你需要表述這樣一個目的: “黃色button會一直水準居中,藍色button左邊緣會一直跟黃色button左邊緣對齊。”   你已經為第一種情況建立了一個限制,但是第二個并沒有。Interface Builder為對齊顯示了向導線,這樣你就可以将上面button一直拖拽到跟黃色左邊緣對齊的位置:

iOS Auto Layout 1

  如果你也在垂直方向上拖拽button,這時button架構和Vertical Space限制之間就不能達到正确的距離了。你在T-bar上将會看到橙色的badge:

iOS Auto Layout 1

如果發生這樣的情況,簡單的使用方向鍵将button微調到位,直到badge消失。   最終,按住Ctrl在兩個button間拖拽,從彈出菜單中選擇Left。這會建立一個限制:“兩個視圖的左邊緣一直對齊”。換句話說,這兩個button一直會有相同的X軸坐标。這時T-bars變成藍色了:

iOS Auto Layout 1

  運作程式并旋轉到橫屏模式:

iOS Auto Layout 1

  何去何從? 現在你已經對自動布局進行了第一次嘗試,感覺怎麼樣?這可能需要一些時間習慣,但是它能讓你的工作更加簡單,也會讓你的app更加靈活。   想要學習更多的内容?繼續閱讀 第二部分吧,你将會繼續在Interface Builder中使用button進一步了解Auto Layout提供的多種可能性,以及你可能遇到的問題。   最重要的是,你将會使用Auto Layout在一個真實的程式中建立一個逼真的布局。