發佈於:2013-12-03 13:53閱讀數:85091html
到目前爲止,若是你的設計至關的複雜,那麼你必須編寫大量的代碼來適應這樣的佈局。你應該很高興,如今這樣的狀況不再存在了--iOS6爲iPhone和iPad帶來了一個極好的新特性:自動佈局。Xios
「」spring
閱讀器微信
原文:Beginning Auto Layout Tutorial in iOS 7: Part 1app
感謝翻譯小組成員@answer-huang(博客)熱心翻譯。若是您有不錯的原創或譯文,歡迎提交給咱們,更歡迎其餘朋友加入咱們的翻譯小組(聯繫qq:2408167315)。框架
==========================================================================ide
提示:團隊成員Jatthijs Hollemans(iOS 初級系列做者)已經將這篇文章移植到iOS7 feast上。但願你可以喜歡。工具
你是否曾經想讓你的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":
點擊Main.storyboard。在你作別的以前,首先將這個storyboard的自動佈局關了。你須要在File inspector,第一個選項的第六個tabs裏:
將Use Autolayout的box勾選去掉。如今storyboard使用舊的struts-and-springs模型。
注意:任何你使用Xcode4.5或更高版本中,nib或者storyboard文件都默認激活了自動佈局。由於自動佈局是iOS6以及以上系統的一個新特性,若是你想使用最新的Xcode開發兼容iOS5的程序,你須要將這個選項去掉。
拖拽三個新的視圖到主視圖上,而且像這樣排列起來:
爲了表述更清楚,這裏給出每一個視圖的顏色,這樣你就能分清哪一個是驢子哪一個是馬了。
每一個視圖的inset到窗口的距離都是20點;視圖之間的距離也是20點。底部的視圖的寬是280點,上面兩個視圖的寬都是130點。全部的視圖的高都是254。
在iPhone Retina 4-inch simulator上運行這個程序,而且將模擬器旋轉到landscape。程序看起來便變成這副鬼樣,這不是我想象的那樣:
注意:你可使用Hardware\Rotate Left和Rotate Right菜單選項旋轉模擬器,或者經過按下鍵盤上的? 鍵,同時按下←或→。
而你想象的程序在landscape應該像這樣:
很明顯,三個視圖的autosizing masks留下了一些須要改進的地方。將左上方視圖的autosizing設置改爲這樣:
這將會讓視圖貼附左上邊緣(不是右下邊緣),而且當父視圖大小改變時,從新調整自身水平和垂直方向的大小。
一樣的,右上方視圖的autosizing設置改爲這樣:
底部視圖:
再次運行程序,而且旋轉到landscape。如今看起來像這樣:
已經很接近了,但又不徹底同樣。視圖之間的padding不正確。換個說法就是視圖的大小不徹底正確。問題出在當父視圖改變大小時,autosizing masks告訴子視圖調整大小,但又沒告訴子視圖該調整多少(坑兒?)。
你能夠調戲autosizing masks-好比,改變靈活寬度和高度設置(springs)-你不會獲得徹底正確的三個間距20點的視圖。
爲了解決這個springs和struts方法的佈局問題,很是不幸,你須要額外寫一些代碼。
在旋轉用戶界面以前、之間、以後,UIKit會發送一些消息到你的視圖控制器,你能夠截獲這些消息,從而對你UI作出改變。表明性的像viewWillLayoutSubviews,你會重寫這個方法從而改變任何須要從新排列的視圖的frame。
在這以前,你須要先作出一個outlet屬性來引用這個視圖。
切換到Assistant Editor模式,按住Ctrl,將三個視圖都拖到ViewController.m中去:
分別連接視圖到這三個屬性:
@property (weak, nonatomic) IBOutlet UIView *topLeftView; @property (weak, nonatomic) IBOutlet UIView *topRightView; @property (weak, nonatomic) IBOutlet UIView *bottomView;
下面的代碼寫到ViewController.m:
- (void)viewWillLayoutSubviews { if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { CGRect rect = self.topLeftView.frame; rect.size.width = 254; rect.size.height = 130; self.topLeftView.frame = rect; rect = self.topRightView.frame; rect.origin.x = 294; rect.size.width = 254; rect.size.height = 130; self.topRightView.frame = rect; rect = self.bottomView.frame; rect.origin.y = 170; rect.size.width = 528; rect.size.height = 130; self.bottomView.frame = rect; } else { CGRect rect = self.topLeftView.frame; rect.size.width = 130; rect.size.height = 254; self.topLeftView.frame = rect; rect = self.topRightView.frame; rect.origin.x = 170; rect.size.width = 130; rect.size.height = 254; self.topRightView.frame = rect; rect = self.bottomView.frame; rect.origin.y = 295; rect.size.width = 280; rect.size.height = 254; self.bottomView.frame = rect; } }
當視圖控制器旋轉到一個新的方向,這個回調將會被調用。它會監控視圖控制器旋轉的方向,而且適當的調整視圖大小-在這種狀況,根據已知iPhone屏幕大小會有一個hard-code(將可變變量用一個固定值來代替的方法叫作hard-code)偏移。這個回調會在一個動畫block中發生,因此會動態的改變大小。
暫時還不要運行這個程序。首先你須要按下面的樣子從新保存三個視圖的autosizing masks,不然autosizing mechanism將會和你在viewWillLayoutSubviews中設置的位置和大小衝突。
這樣就能夠了,運行程序而且翻轉到landscape。如今視圖排列的很是號。翻轉回到portrait,經覈實,一切都良好。
這樣奏效了,可是你須要爲這個很是簡單的例子編寫大量的佈局代碼。想象一下,爲佈局付出的努力是很是複雜的,特別是個別視圖動態的改變大小,或者子視圖的個數是不固定的。
如今試着在3.5寸的模擬器上運行程序。我了個去。視圖的位置和大小又錯了,由於viewWillLayoutSubviews的hard-code座標是基於4英寸大小的手機(320x568取代320x480)。你能夠增長另外一個if語句判斷屏幕大小,並使用不一樣的座標集,可是你能夠看到這個方法很快變得不切實際。
注意:另外一個你能夠採起的方法就是爲portrait和landscape模式創建獨立的nibs。當設備旋轉時,你從另外一個nib中裝載視圖並替換掉當前的那個。但這任然須要作不少工做,而且維護兩個nibs也會增長問題。當你使用storyboards替代nibs的時候,這個方法也變得不切實際。
自動佈局拯救猿!
如今你將會看到如何用自動佈局實現相同的效果,從ViewController.m中移除viewWillLayoutSubviews,由於咱們再也不須要寫任何代碼。
選擇Main.storyboard,並在File inspector中選擇開啓Use Autolayout:
運行程序,旋轉到landscape。如今看起來像這樣:
讓咱們把自動佈局付諸行動。當你點擊頂部兩個視圖時,按住?鍵,這樣兩個視圖都被選中了。從Xcode的Editor菜單中選擇Pin\Widths Equally:
再次選中兩個相同的視圖,選擇Editor\Pin\Horizontal Spacing。(儘管你執行完第一次Pin處理後,兩個視圖看起來仍是被選中的,但其實他們只是在一個特別的佈局關係顯示模型裏。因此你須要從新選擇這兩個視圖)
storyboard如今看起來像這樣:
橙色的"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
如今你應該有了下面這些約束:
注意T-bars仍然是橘黃色的。這意味這你的佈局沒有完成;自動佈局沒有足夠的約束條件計算出視圖的位置和大小。解決辦法即是增長更多約束,直到他們變藍。
按下? 鍵並選中三個視圖。從Editor菜單中,選擇Pin\Heights Equally。
如今選中左上角的視圖和底部視圖(像前面同樣按住? 鍵),選擇Editor\Pin\Vertical Spacing.
Interface Builder看起來應該像這樣:
T-bars已經變藍了。自動佈局如今已經有足夠的信息來計算出一個有效的佈局。這看起來有點雜亂無章,這是由於等寬和等高約束條件佔去了很大空間。
運行程序而且...我說吧,不須要寫一行代碼便運行的很好了。無論你在哪一個模擬器上運行;在3.5英寸和4英寸設備上,佈局都運行良好。
這很是酷,可是究竟你在這作了什麼?自動佈局讓你表達出佈局中的視圖和其餘每一個視圖的關係,而不是須要你指出視圖有多大,放在哪兒。你須要放置如下這些關係(即咱們所謂的約束)到佈局中:
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相對於父視圖的約束)。
這些就足以表達出自動佈局該怎麼放置視圖,以及當屏幕大小改變時該如何處理。
你能夠在左邊Document Outline中看到你全部的約束,組名叫作Constraints(當你爲storyboard激活自動佈局時纔會加進來)。
若是你在Document Outline中點擊一個約束,Interface Builder將會在視圖中高亮出它:
約束是一個真實的對象(NSLayoutConstraint),而且他們也有屬性。好比,選擇上面兩個視圖的間距約束條件(叫作"Horizontal Space(20)"),而後切換到Attributes inspector。你能夠在那裏經過編輯Constant字段改變邊緣空間的大小。
將它設置爲100,而後再次運行程序。如今他們邊緣空間變得更寬了:
自動佈局在描述視圖上比springs和struts顯得更有表現力。在這篇教程的剩餘部分,你將會學到約束的一切,以及如何將他們應用到Interface Builder上來構造出不一樣種類的佈局。
自動佈局如何工做
正如你在上面測試樣例中所看到的同樣,自動佈局最基本的工具是約束。一個約束描述了兩個視圖間的幾何關係。好比,你可能有這樣一個約束:
"label A右邊緣和button B左邊緣有20點的空白空間。"
自動佈局會考慮到全部的約束,而後爲你的視圖計算出理想的位置和大小。你不再須要親自爲你的視圖設置frames了-自動佈局會徹底基於你爲這些視圖設置的約束爲你作這個工做。
自動佈局之前,你一直須要爲視圖的frames設置hard-code,要麼在Interface Builder中將他們放置在特定的座標,或經過傳遞一個rectangle到initWithFrame:,或者設置視圖的frame,bounds或者center屬性。
就你剛剛作的那個程序,你須要明確設置frames爲:
還須要爲這些視圖設置自動調整大小的masks:
這不再是你須要爲屏幕設計所考慮的東西了。使用自動佈局,你須要作這些:
視圖的大小和位置不再重要了,只有約束要緊。固然,當你拖一個新建的button或label到畫布上時,它會有必定的大小,而且你會將它拖到某一位置,但這是隻一個用來告訴Interface Builder如何放置約束的設計工具。
想你所想,如你所願
使用約束最大的優點就是你不再須要把時間浪費在座標上了。相反,你能夠向自動佈局描述視圖如何和其餘視圖相關聯,自動佈局將會爲你完成全部困難的工做。這叫作根據目的設計(designing by intent)。
當你根據目的設計時,你表達的是你想要實現什麼,而不須要關心它如何實現。"button的左上角座標爲(20,230)",如今你能夠這麼說了:button是垂直居中於它的父視圖,而且相對於父視圖的左邊緣有一個固定的距離。
使用這個描述,無論父視圖多大或多小,自動佈局均可以自動計算出你的button須要在哪兒出現,
其餘根據目的設計的示例(自動佈局能夠處理全部這些指令):
"這兩個text fields的大小須要一直相等。"
"這兩個button須要一直一塊兒移動。"
"這四個labels須要一直右對齊。"
這使得你用戶界面的設置更具描述性。你只需簡單的定義約束,系統會爲你自動計算frames。
在第一部分你看到,即便爲幾個視圖在橫豎方向上正確的佈局都須要作大量的工做。有了自動佈局,你能夠繞過這些麻煩。若是你正確的設置了約束,那麼在橫豎屏方向上,佈局將不須要作任何改變。
使用自動佈局另外一個重要的好處就是本地化。好比德語中的文本,出了名的比老奶奶的裹腳布還要長,適配起來是一件很麻煩的事。再次,自動佈局拯救了猿,由於它能根據label須要顯示的內容自動改變label的大小。
如今增長德語,法語或者其餘任何一種語言,都只是設置約束的事,而後翻譯文本,而後。。。就沒有而後了!
得到自動佈局竅門最好的方法就是使用它,因此這正是剩下教程中你會學到的東西。
注意:自動佈局不只對旋轉有做用;它還能輕易的縮放你UI的大小從而適應不一樣尺寸的屏幕。這並非巧合,當iPhone5擁有更高屏幕的同時,這個技術也同時加到了iOS中!自動佈局能輕易的拉伸你程序的用戶界面,從而充滿iPhone5垂直方向上多出來的空間。隨着iOS7中的動態類型,自動佈局變得更加劇要了。用戶如今能夠改變全局字體大小設置--有了自動佈局,這將變得很是簡單。
擁抱約束(courting constraints)
關閉你當前的項目並用Single View Application模板建立一個新的iPhone項目。叫作"Constraints"。任何用Xcode5建立出來的項目都會自動假定你會使用自動佈局,因此你並不須要額外作任何事情。
點擊Main.storyboard打開Interface Builder。拖一個新的Button到畫布上。注意當你拖拽的時候,藍色虛線將會出現。這寫線用來作嚮導。
在屏幕邊緣以及中心的時候,都會有嚮導線:
若是以前你已經使用過Interface Builder,那麼你確定看到過這些嚮導線。這對咱們對齊控件有很大的幫助。
在Xcode4中激活自動佈局時,嚮導線有另一個目的。你任然能夠用他們來對齊,可是他們也會告訴你新的約束將會在哪兒。若是你將button沿着嚮導線反方向拖拽到左上角時,Xcode4中的storyboard看起來便像這樣:
有兩個藍色的東西附屬在button上面。這些T-bar形狀的對象即是約束了。Xcode 4的Interface Builder中無論你將UI控制器放在哪兒,它老是會給出有效的約束。理論上這聽起來是個好主意,可是實踐起來,在Interface Builder中使用自動佈局卻很是困難。
幸運的是,Xcode5中已經有所好轉。將button拖拽到畫布上以後並看不到T-bars形狀的東西:
同時在Document Outline面板中也沒用Constraints部分。獲得結論:此時button上並無設置任何約束。
那這是如何運做的呢?咱們以前瞭解的自動佈局老是須要足夠多的約束才能決定視圖的大小和位置,可是如今咱們這兒跟本沒有約束。肯定這是一個完整的佈局?
這這是Xcode5相對Xcode4來講最大的一個提高:不再強制你老是有一個有效的佈局。
注意:1.運行一個無效佈局的程序是不明智的,由於自動佈局不能正確的計算須要將視圖放在哪兒。要麼視圖的位置是不可預知的(約束不夠),要麼程序將會崩潰(約束過多)。
2.Xcode4設法保證老是有足夠多正確的約束來建立一個有效的佈局。不幸的是,它常常會將你的約束替換爲你並不想要的。這會使人很沮喪,正是由於這個緣由不少開發者放棄了自動佈局。
3.Xcode5中,當你編輯Storyboard時它容許你有不完整的佈局,但它也會指出哪些地方你還須要修改。使用Interface Builder建立的自動佈局驅動用戶界面變得更有趣了,使用Xcode5也消耗更少的時間。
若是你根本不提供任何約束,Xcode自動分配一套默認的約束,正是咱們所知的自動約束。它會在程序built的編譯時間中去完成這些事,而不是設計時間。當你設計你的用戶界面時,Xcode5中的自動佈局爲了避免參與你的設計方法而努力工做,這這是咱們喜歡它的緣由。
自動約束爲你的視圖提供一個固定尺寸和位置。換句話說,視圖老是擁有跟你在storyboard中看到的同樣的座標。這是很是方便的,由於這就意味着你能夠大量的忽視自動佈局。你能夠爲那些擁有充分約束的控件不增長約束,只爲那些須要特殊規則的視圖建立約束。
OK,讓咱們玩一玩約束並看看他們能作什麼。如今,按鈕是在左上角,而且沒有約束。確認按鈕跟兩個拐角嚮導線對齊。
使用Editor\Pin菜單爲按鈕增長兩個新的約束,看起來像這樣:
這是Leading Space to Superview和Top Space to Superview選項。
全部的約束都會在Document Outline面板中列出來:
目前有兩個約束,一個是button和main view左邊緣的Horizontal Space約束,一個是button和main view上邊緣的Vertical Space約束。這個關係經過約束描述起來即是:"button老是位於其父視圖左上角20點處。"
注意:這些其實都不是很是有用的約束,由於他們有相同的自動約束。若是你老是想你的button相對於父視圖左上角,那麼你還不如不提供任何約束,讓Xcode爲你作這些。
如今拖動button並將它放到屏幕的右上角,再次和藍色嚮導線對齊:
哇哦,這裏發生了什麼?在Xcode4中這會破壞舊的約束並賦值一個基於藍色嚮導線的新約束,可是在Xcode5中button保留了現存的約束。但問題是button在Interface Builder中的大小和位置不再和自動佈局但願基於約束的大小和位置相符合了。這叫作錯位的視圖。(misplaced view)
運行程序。Button仍然會出如今屏幕的左上角:
當談到自動佈局,橙色表明壞的。Interface Builder繪製兩個橙色方塊:一個是虛線邊框,一個是實線邊框。虛線方塊是根據自動佈局顯示視圖的frame。實線方塊是根據你在屏幕上放置的視圖的frame。這兩個應該吻合的,可是這裏並無。
如何修改取決於你想要達到什麼目的:
1.你想讓button附屬於屏幕左邊緣254點處嗎?在這種狀況下你須要將現存的Horizontal Space約束變大234點。這正是橙色badge中"+234"的意思。
2.你想讓button附屬於屏幕的右邊緣?那麼你須要移除現有的約束並從新建立一個新的。
刪除Horizontal Space約束。首先在畫布或Document Outline中選中,而後按鍵盤上的Delete鍵。
注意此次Vertical Space約束變橙色了。直到如今它都是藍色的。那一個約束並無任何錯誤;它的意思是剩下的沒有足夠的約束決定button完整的位置。你任然須要在X軸方向增長一個約束。
Note:你可能會奇怪,爲何Xcode不爲X軸方向自動增長一個約束。Xcode中的規則是:Xcode只爲那些你沒有設置任何約束的對象建立自動約束。一旦你增長一個約束,你即是告訴Xcode你接管了這個視圖。Xcode將再也不增長任何自動約束,並但願你爲這個視圖增長鬚要的約束。
選中button,並選擇Editor\Pin|Trailing Space to Superview.這迫使在button右邊緣和屏幕右邊緣增長一個新的約束。關係表達以下:"button老是位於距離其父視圖右上角20點處。"
運行程序並旋轉到landscape。注意button如何與屏幕右邊緣保持相同距離:
當你放置一個對立於嚮導線的button(或者任何其餘視圖)並新建一個約束時,你會獲得一個根據"HIG"(Apple's iOS Human Interface Guidelines document)定義的標準大小的間隔約束。對於邊框來講,標準大小空間是20點。
如今將button向左拖拽一點:
因爲視圖錯位,你獲得了一個橙色虛線邊框。咱們假設這個button新位置的確是你想要的。建立完一個約束後作一些細微的調整是很常見的,但這卻會致使橙色方塊出現。一個修改方法就是移除約束並建立一個新的,但還有一個更簡單的解決方案。
Editor菜單上有一個Resolve Auto Layout Issues子菜單。從這個菜單中,選中Update Constraints。就我這個狀況來講,這會告訴Interface Builder須要將約束變大64點,像這樣:
很好,T-bars又變藍了,佈局是有效的。在Document Outline中,你能夠看到Horizontal Space約束再也不有一個標準的間隔了:
到目前爲止你已經嘗試過了Horizontal Space和Vertical Space約束。還有一個"center"約束。拖拽一個新的Button對象到畫布底部中心,根據嚮導線無缺入位:
爲了保持button在水平方向上一直居中對齊於父視圖,你須要增長一個Center X Alignment約束。從Editor菜單選擇Align\Horizontal Center in Container.這會增長一個很長的橙色線段:
線之因此是橙色是由於你才僅僅指定了button的X軸,但Y軸並無指定約束。使用Editor\Pin菜單在button和視圖底部間增長一個Vertical Space約束。看起來像這樣:
若是你不知道緣由,這是Bottom Space to Superview選項。Vertical Space約束使button遠離視圖底部(再一次使用標準間隔)。
運行程序並旋轉到橫屏模式。甚至在橫屏模式,button也保持在屏幕底部的中心:
這就是你表達的意思---這個button始終應該位於底部中心。注意,你根本不須要告訴Interface Builder按鈕的座標是什麼,除非你想將它固定在視圖上。
經過自動佈局,你不再須要擔憂視圖位置的精確座標或視圖大小了。相反,自動佈局會根據你設置的約束獲得這兩個參數。
你能夠在button的Size inspector中看到這個經典轉移,如今有了很大的不一樣:
若是不使用自動佈局,輸入值到X,Y,Width或Height字段將會改變選中視圖的位置和大小。使用自動佈局後,你仍然能夠輸入新值到這些字段,可是若是你已經爲視圖設置了約束,那這可能形成視圖錯位。你將不得不更新約束來匹配新值。
舉個例子,把button的寬度改成100,畫布會變成這樣:
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:
選中那個T-bar並在Attributes inspector中改變Constant爲100.無論button的title多大或多小,這都會強制button的寬老是100點。爲了能更好的看清你能夠給button設置一個背景色:
你也能夠在左邊的Document Outline中看到這個新的Width約束:
與其餘約束不一樣,在button和它的父視圖之間,Width約束只會應用到button自己。你能夠將這個認爲是一個button自己和自己之間的約束。
你可能懷疑爲何button以前沒有Width約束。自動佈局是爲什麼知道button有多寬?
事情是這樣的:button本身是知道本身有多寬。它根據本身的title text加上一些padding就好了。若是你爲button設置一個背景圖片,它也會考慮進去。
這正是咱們熟悉的intrinsic content size。並非全部的控制器都有這個,但大部分是(UILabel是一個例子)。若是一個視圖能夠計算本身理想的大小,那麼你就不須要爲它特別指定Width或Height約束了,你將會在稍後看到更多相關內容。
爲了恢復button到最佳大小,首先咱們須要移除Width約束。而後選中button,並從Editor菜單中選擇Size to Fit Content。這樣就可以恢復button的固有的內容尺寸了。
孤掌難鳴
嚮導線不但出如今一個視圖和它的父視圖之間,並且也會出如今相同層級的視圖之間。拖拽一個新的button到畫布上進行演示。若是你將這個button拖近其餘對象,這時他們的嚮導線將會開始相互影響。
將新button放到以前一個button的後面無缺入位:
這還有一些嚮導虛線。Interface Builder識別出這兩個button能夠經過不一樣方式對齊—頂部,中心以及基線。
Xcode4會將這些顯著的嚮導線轉變成新的約束。可是在Xcode5中,若是你想讓這兩個button間有約束,你須要本身建立。以前你已經使用過Editor\Pin菜單來建立這兩個視圖間的約束,可是還有一個更簡單的方式。
選中新的button並按住Ctrl拖拽到另外一個button上,像這樣:
放開鼠標按鍵,出現一個彈出框。選擇第一個選項,Horizontal Spacing。
這將會建立一個新的約束:
它是橙色的,這意味着這個button至少還須要另外一個約束。button的大小是知道的(使用intrinsic content size),而且還有一個button在X軸上的約束。只剩下Y軸沒有約束了。
這種缺失約束的狀況是很容易肯定的,可是更復雜的設計可能就沒這麼明顯了。幸運的是,你再也不須要敏思苦想,Xcode已經記錄並能夠確切的告訴你缺乏了什麼。
在Document Outline中會有一個紅色的小箭頭,就在View Controller Scene後面。點擊這個箭頭便會看到全部Auto Layout問題:
咱們將Y軸方向缺失的約束加進去。按住Ctrl並向下拖拽新的button:
此次彈出菜單有不一樣的選項了。此次菜單的選項是基於上下文環境的—你在哪些視圖間拖拽以及鼠標移動的方向。選擇Bottom Space to Bottom Layout。
如今新button有一個位於屏幕底部的Vertical Space,也有一個跟其餘button相關聯的Horizontal Space。雖然空間很是小(只有8 points),T-bar可能不大容易看到,但它就在那裏。
點擊Document Outline裏面的Horizontal Space(8):
當你選中一個約束,它會高亮本身所屬的控制器。這個特別的約束位於兩個button之間。這個約束表達了:「無論第一個button在哪兒或多大,第二個button老是出如今第一個button的左邊」。
選中黃色背景的button並輸入較長的label,好比:「A longer label」。輸入完成後,button會爲新的text改變大小,而且另外一個button會移開。
最終,它依附在第一個button的左邊緣,這正是咱們所指望的:
爲了更好的摸索這是如何工做的,多練一些吧。拖拽另外一個button到畫布上並放到黃色button的上方,他們會垂直方向對齊到位(不要試着讓兩個button的左邊緣對齊):
爲新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:
在Constant字段裏輸入40改變約束大小。如今兩個button更進一步的分開了,可是他們任然是鏈接在一塊兒的:
運行程序並翻轉到landscape模式查看效果:
button必然會保持他們垂直方向的排列,可是水平方向就不了!緣由很明顯:綠色button尚未X軸方向的約束。
爲綠色button增長一個到屏幕左邊緣的Horizontal Space並不能解決問題。這樣的約束只會讓綠色按鈕老是保持在同一個X軸座標,即使是在橫屏模式下。這看起來感受不大對,因此你須要表述這樣一個目的:
「黃色button會一直水平居中,藍色button左邊緣會一直跟黃色button左邊緣對齊。」
你已經爲第一種狀況建立了一個約束,可是第二個並無。Interface Builder爲對齊顯示了嚮導線,這樣你就能夠將上面button一直拖拽到跟黃色左邊緣對齊的位置:
若是你也在垂直方向上拖拽button,這時button框架和Vertical Space約束之間就不能達到正確的距離了。你在T-bar上將會看到橙色的badge:
若是發生這樣的狀況,簡單的使用方向鍵將button微調到位,直到badge消失。
最終,按住Ctrl在兩個button間拖拽,從彈出菜單中選擇Left。這會建立一個約束:「兩個視圖的左邊緣一直對齊」。換句話說,這兩個button一直會有相同的X軸座標。這時T-bars變成藍色了:
運行程序並旋轉到橫屏模式:
何去何從?
如今你已經對自動佈局進行了第一次嘗試,感受怎麼樣?這可能須要一些時間習慣,可是它能讓你的工做更加簡單,也會讓你的app更加靈活。
想要學習更多的內容?繼續閱讀第二部分吧,你將會繼續在Interface Builder中使用button進一步理解Auto Layout提供的多種可能性,以及你可能遇到的問題。
最重要的是,你將會使用Auto Layout在一個真實的程序中建立一個逼真的佈局。
CocoaChina是全球最大的蘋果開發中文社區,官方微信每日定時推送各類精彩的研發教程資源和工具,介紹app推廣營銷經驗,最新企業招聘和外包信息,以及Cocos2d引擎、Cocos Studio開發工具包的最新動態及培訓信息。關注微信能夠第一時間瞭解最新產品和服務動態,微信在手,天下我有!
請搜索微信號「CocoaChina」關注咱們!