自動布局教程

開始iOS 7中自動布局教程(一)

發(fā)布于:2013-12-03 13:53閱讀數(shù):86977

到目前為止,如果你的設計相當?shù)膹碗s麻惶,那么你必須編寫大量的代碼來適應這樣的布局。你應該很高興信夫,現(xiàn)在這樣的情況再也不存在了--iOS6為iPhone和iPad帶來了一個極好的新特性:自動布局窃蹋。X

“”

閱讀器

原文:Beginning Auto Layout Tutorial in iOS 7: Part 1

感謝翻譯小組成員@answer-huang博客)熱心翻譯。如果您有不錯的原創(chuàng)或譯文静稻,歡迎提交給我們警没,更歡迎其他朋友加入我們的翻譯小組(聯(lián)系qq:2408167315)。

==========================================================================

提示:團隊成員Jatthijs Hollemans(iOS 初級系列作者)已經(jīng)將這篇文章移植到iOS7 feast上振湾。希望你能夠喜歡杀迹。

你是否曾經(jīng)想讓你的app在橫豎屏方向上看起來都表現(xiàn)良好而受挫?是否在做支持iPhone和iPad屏幕布局界面時幾近大小便失禁押搪?今天我將給你帶來好消息树酪!

一直為大小相同的屏幕設計一個用戶界面并不難浅碾,但如果屏幕的尺寸改變的話,UI元素的位置和大小也需要相應的做出改變续语。

到目前為止垂谢,如果你的設計相當?shù)膹碗s,那么你必須編寫大量的代碼來適應這樣的布局疮茄。你應該很高興埂陆,現(xiàn)在這樣的情況再也不存在了--iOS6為iPhone和iPad帶來了一個極好的新特性:自動布局。Xcode 5和 iOS7中對自動布局做出了改善娃豹!如果你曾經(jīng)嘗試著在Xcode4中使用自動布局并最終做出放棄焚虱,現(xiàn)在是該給Xcode5一次機會了。

在你的程序中懂版,自動布局不僅可以很容易的支持不同大小的屏幕鹃栽,一個額外的功能,它也使得本地化幾乎變得微不足道躯畴。你不再需要為每種你希望支持的語言創(chuàng)建新的nibs或storyboards民鼓,包括像Hebrew或Arabic這樣從右到左的語言。

這個教程將向你展示如何使用Interface Builder開始自動布局.在iOS6 教程中蓬抄,我們進一步討論過這個教程丰嘉,然后有一個基于這個知識點完整的新章節(jié),并且向你展示如何通過代碼完全釋放出自動布局的能量嚷缭。

注意:我們已經(jīng)開始將iOS6教程中相應的章節(jié)更新到iOS7-這只是先給大家解解饞饮亏!當我們完成后,所有iOS6 PDF教程的訂閱者將會得到免費的更新下載阅爽。

so路幸,備好零食和你喜歡的咖啡,準備成為自動布局的達人吧付翁!

springs和struts的問題

你肯定很熟悉autosizing masks-也被認為是springs&struts模式简肴。autosizing mask決定了當一個視圖的父視圖大小改變時,其自身需要做出什么改變百侧。它有一個靈活的或固定不變的margins(struts)嗎砰识?它的寬和高要做出什么改變(springs)?

舉個例子佣渴,一個寬度靈活的視圖辫狼,如果其父視圖邊框,那么它也會相應的變寬观话。一個視圖右邊擁有固定的margin予借,那么它的右邊緣將會一直粘住其父視圖的右邊緣越平。

autosizing系統(tǒng)在簡單的情況下非常奏效频蛔,但當你布局變得更復雜時灵迫,它立馬跪了。讓我們看一個springs和struts不能處理的示例晦溪。

打開Xcode5瀑粥,創(chuàng)建一個基于Single View Application模板的iPhone項目。叫做"StrutsProblem":

點擊Main.storyboard三圆。在你做別的之前狞换,首先將這個storyboard的自動布局關(guān)了。你需要在File inspector舟肉,第一個選項的第六個tabs里:

將Use Autolayout的box勾選去掉⌒拊耄現(xiàn)在storyboard使用舊的struts-and-springs模型。

注意:任何你使用Xcode4.5或更高版本中路媚,nib或者storyboard文件都默認激活了自動布局黄琼。因為自動布局是iOS6以及以上系統(tǒng)的一個新特性,如果你想使用最新的Xcode開發(fā)兼容iOS5的程序整慎,你需要將這個選項去掉脏款。

拖拽三個新的視圖到主視圖上,并且像這樣排列起來:

為了表述更清楚裤园,這里給出每個視圖的顏色撤师,這樣你就能分清哪個是驢子哪個是馬了。

每個視圖的inset到窗口的距離都是20點拧揽;視圖之間的距離也是20點剃盾。底部的視圖的寬是280點,上面兩個視圖的寬都是130點淤袜。所有的視圖的高都是254万俗。

在iPhone Retina 4-inch simulator上運行這個程序,并且將模擬器旋轉(zhuǎn)到landscape饮怯。程序看起來便變成這副鬼樣闰歪,這不是我想象的那樣:

注意:你可以使用Hardware\Rotate Left和Rotate Right菜單選項旋轉(zhuǎn)模擬器,或者通過按下鍵盤上的?鍵蓖墅,同時按下←或→库倘。

而你想象的程序在landscape應該像這樣:

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

這將會讓視圖貼附左上邊緣(不是右下邊緣),并且當父視圖大小改變時教翩,重新調(diào)整自身水平和垂直方向的大小。

同樣的贪壳,右上方視圖的autosizing設置改成這樣:

底部視圖:

再次運行程序饱亿,并且旋轉(zhuǎn)到landscape。現(xiàn)在看起來像這樣:

已經(jīng)很接近了,但又不完全一樣彪笼。視圖之間的padding不正確钻注。換個說法就是視圖的大小不完全正確。問題出在當父視圖改變大小時配猫,autosizing masks告訴子視圖調(diào)整大小幅恋,但又沒告訴子視圖該調(diào)整多少(坑兒?)泵肄。

你可以調(diào)戲autosizing masks-比如捆交,改變靈活寬度和高度設置(springs)-你不會得到完全正確的三個間距20點的視圖。

為了解決這個springs和struts方法的布局問題腐巢,非常不幸品追,你需要額外寫一些代碼。

在旋轉(zhuǎn)用戶界面之前冯丙、之間诵盼、之后,UIKit會發(fā)送一些消息到你的視圖控制器银还,你可以截獲這些消息风宁,從而對你UI做出改變。代表性的像viewWillLayoutSubviews蛹疯,你會重寫這個方法從而改變?nèi)魏涡枰匦屡帕械囊晥D的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;

}

}

當視圖控制器旋轉(zhuǎn)到一個新的方向列吼,這個回調(diào)將會被調(diào)用幽崩。它會監(jiān)控視圖控制器旋轉(zhuǎn)的方向,并且適當?shù)恼{(diào)整視圖大小-在這種情況寞钥,根據(jù)已知iPhone屏幕大小會有一個hard-code(將可變變量用一個固定值來代替的方法叫做hard-code)偏移慌申。這個回調(diào)會在一個動畫block中發(fā)生,所以會動態(tài)的改變大小理郑。

暫時還不要運行這個程序蹄溉。首先你需要按下面的樣子重新保存三個視圖的autosizing masks,否則autosizing mechanism將會和你在viewWillLayoutSubviews中設置的位置和大小沖突您炉。

這樣就可以了柒爵,運行程序并且翻轉(zhuǎn)到landscape。現(xiàn)在視圖排列的非常號赚爵。翻轉(zhuǎn)回到portrait棉胀,經(jīng)核實法瑟,一切都良好。

這樣奏效了唁奢,但是你需要為這個非常簡單的例子編寫大量的布局代碼霎挟。想象一下,為布局付出的努力是非常復雜的驮瞧,特別是個別視圖動態(tài)的改變大小氓扛,或者子視圖的個數(shù)是不固定的枯芬。

現(xiàn)在試著在3.5寸的模擬器上運行程序论笔。我了個去。視圖的位置和大小又錯了千所,因為viewWillLayoutSubviews的hard-code坐標是基于4英寸大小的手機(320x568取代320x480)狂魔。你可以增加另一個if語句判斷屏幕大小,并使用不同的坐標集淫痰,但是你可以看到這個方法很快變得不切實際最楷。

注意:另一個你可以采取的方法就是為portrait和landscape模式建立獨立的nibs。當設備旋轉(zhuǎn)時待错,你從另一個nib中裝載視圖并替換掉當前的那個籽孙。但這任然需要做很多工作,并且維護兩個nibs也會增加問題火俄。當你使用storyboards替代nibs的時候犯建,這個方法也變得不切實際。

自動布局拯救猿瓜客!

現(xiàn)在你將會看到如何用自動布局實現(xiàn)相同的效果适瓦,從ViewController.m中移除viewWillLayoutSubviews,因為我們不再需要寫任何代碼谱仪。

選擇Main.storyboard玻熙,并在File inspector中選擇開啟Use Autolayout:

運行程序,旋轉(zhuǎn)到landscape》柙埽現(xiàn)在看起來像這樣:

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

再次選中兩個相同的視圖,選擇Editor\Pin\Horizontal Spacing筷转。(盡管你執(zhí)行完第一次Pin處理后姑原,兩個視圖看起來還是被選中的,但其實他們只是在一個特別的布局關(guān)系顯示模型里呜舒。所以你需要重新選擇這兩個視圖)

storyboard現(xiàn)在看起來像這樣:

橙色的"T-bar"形狀代表視圖間的約束锭汛。目前為止你增加了兩個約束:一個等寬約束和一個位于兩個視圖間的水平約束。約束表達了視圖之間的關(guān)系,并且他們是你使用自動布局建立布局最主要的工具唤殴。這貨看起來有點嚇人般婆,但是一旦弄懂它的意思,便變得相當簡單朵逝。

為了繼續(xù)為這個屏幕簡歷布局蔚袍,執(zhí)行下面這些步驟。每個步驟增加更多橘黃色的T-bars.

oTop Space to Superview

oLeading Space to Superview

For the view on the right, choose:

oTop Space to Superview

oTrailing Space to Superview

And for the big view at the bottom:

oLeading Space to Superview

oTrailing Space to Superview

oBottom Space to Superview

現(xiàn)在你應該有了下面這些約束:

注意T-bars仍然是橘黃色的配名。這意味這你的布局沒有完成啤咽;自動布局沒有足夠的約束條件計算出視圖的位置和大小。解決辦法便是增加更多約束渠脉,直到他們變藍宇整。

按下?鍵并選中三個視圖。從Editor菜單中芋膘,選擇Pin\Heights Equally鳞青。

現(xiàn)在選中左上角的視圖和底部視圖(像前面一樣按住?鍵),選擇Editor\Pin\Vertical Spacing.

Interface Builder看起來應該像這樣:

T-bars已經(jīng)變藍了为朋。自動布局現(xiàn)在已經(jīng)有足夠的信息來計算出一個有效的布局臂拓。這看起來有點雜亂無章,這是因為等寬和等高約束條件占去了很大空間习寸。

運行程序并且...我說吧胶惰,不需要寫一行代碼便運行的很好了。不管你在哪個模擬器上運行融涣;在3.5英寸和4英寸設備上童番,布局都運行良好。

這非惩梗酷剃斧,但是究竟你在這做了什么?自動布局讓你表達出布局中的視圖和其他每個視圖的關(guān)系忽你,而不是需要你指出視圖有多大幼东,放在哪兒。你需要放置以下這些關(guān)系(即我們所謂的約束)到布局中:

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,然后再次運行程序≡技疲現(xiàn)在他們邊緣空間變得更寬了:

自動布局在描述視圖上比springs和struts顯得更有表現(xiàn)力诀拭。在這篇教程的剩余部分迁筛,你將會學到約束的一切煤蚌,以及如何將他們應用到Interface Builder上來構(gòu)造出不同種類的布局。

自動布局如何工作

正如你在上面測試樣例中所看到的一樣细卧,自動布局最基本的工具是約束尉桩。一個約束描述了兩個視圖間的幾何關(guān)系。比如贪庙,你可能有這樣一個約束:

"label A右邊緣和button B左邊緣有20點的空白空間蜘犁。"

自動布局會考慮到所有的約束,然后為你的視圖計算出理想的位置和大小止邮。你再也不需要親自為你的視圖設置frames了-自動布局會完全基于你為這些視圖設置的約束為你做這個工作这橙。

自動布局以前,你一直需要為視圖的frames設置hard-code导披,要么在Interface Builder中將他們放置在特定的坐標屈扎,或通過傳遞一個rectangle到initWithFrame:,或者設置視圖的frame撩匕,bounds或者center屬性鹰晨。

就你剛剛做的那個程序,你需要明確設置frames為:

還需要為這些視圖設置自動調(diào)整大小的masks:

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

視圖的大小和位置再也不重要了,只有約束要緊扁凛。當然忍疾,當你拖一個新建的button或label到畫布上時,它會有一定的大小谨朝,并且你會將它拖到某一位置卤妒,但這是只一個用來告訴Interface Builder如何放置約束的設計工具丸边。

想你所想,如你所愿

使用約束最大的優(yōu)勢就是你再也不需要把時間浪費在坐標上了荚孵。相反妹窖,你可以向自動布局描述視圖如何和其他視圖相關(guān)聯(lián),自動布局將會為你完成所有困難的工作收叶。這叫做根據(jù)目的設計(designing by intent)骄呼。

當你根據(jù)目的設計時,你表達的是你想要實現(xiàn)什么判没,而不需要關(guān)心它如何實現(xiàn)蜓萄。"button的左上角坐標為(20,230)"澄峰,現(xiàn)在你可以這么說了:button是垂直居中于它的父視圖嫉沽,并且相對于父視圖的左邊緣有一個固定的距離。

使用這個描述俏竞,不管父視圖多大或多小绸硕,自動布局都可以自動計算出你的button需要在哪兒出現(xiàn),

其他根據(jù)目的設計的示例(自動布局可以處理所有這些指令):

"這兩個text fields的大小需要一直相等魂毁。"

"這兩個button需要一直一起移動玻佩。"

"這四個labels需要一直右對齊。"

這使得你用戶界面的設置更具描述性席楚。你只需簡單的定義約束咬崔,系統(tǒng)會為你自動計算frames。

在第一部分你看到烦秩,即使為幾個視圖在橫豎方向上正確的布局都需要做大量的工作垮斯。有了自動布局,你可以繞過這些麻煩只祠。如果你正確的設置了約束兜蠕,那么在橫豎屏方向上,布局將不需要做任何改變铆农。

使用自動布局另一個重要的好處就是本地化牺氨。比如德語中的文本,出了名的比老奶奶的裹腳布還要長墩剖,適配起來是一件很麻煩的事猴凹。再次规个,自動布局拯救了猿衔瓮,因為它能根據(jù)label需要顯示的內(nèi)容自動改變label的大小。

現(xiàn)在增加德語移袍,法語或者其他任何一種語言爷绘,都只是設置約束的事书劝,然后翻譯文本进倍,然后。购对。猾昆。就沒有然后了!

獲得自動布局竅門最好的方法就是使用它骡苞,所以這正是剩下教程中你會學到的東西垂蜗。

注意:自動布局不僅對旋轉(zhuǎn)有作用;它還能輕易的縮放你UI的大小從而適應不同尺寸的屏幕解幽。這并不是巧合贴见,當iPhone5擁有更高屏幕的同時,這個技術(shù)也同時加到了iOS中躲株!自動布局能輕易的拉伸你程序的用戶界面片部,從而充滿iPhone5垂直方向上多出來的空間。隨著iOS7中的動態(tài)類型霜定,自動布局變得更加重要了档悠。用戶現(xiàn)在可以改變?nèi)肿煮w大小設置--有了自動布局,這將變得非常簡單然爆。

擁抱約束(courting constraints)

關(guān)閉你當前的項目并用Single View Application模板創(chuàng)建一個新的iPhone項目站粟。叫做"Constraints"黍图。任何用Xcode5創(chuàng)建出來的項目都會自動假定你會使用自動布局曾雕,所以你并不需要額外做任何事情。

點擊Main.storyboard打開Interface Builder助被。拖一個新的Button到畫布上剖张。注意當你拖拽的時候,藍色虛線將會出現(xiàn)揩环。這寫線用來做向?qū)А?/p>

在屏幕邊緣以及中心的時候搔弄,都會有向?qū)Ь€:

如果之前你已經(jīng)使用過Interface Builder,那么你肯定看到過這些向?qū)Ь€丰滑。這對我們對齊控件有很大的幫助顾犹。

在Xcode4中激活自動布局時,向?qū)Ь€有另外一個目的褒墨。你任然可以用他們來對齊炫刷,但是他們也會告訴你新的約束將會在哪兒。如果你將button沿著向?qū)Ь€反方向拖拽到左上角時郁妈,Xcode4中的storyboard看起來便像這樣:

有兩個藍色的東西附屬在button上面浑玛。這些T-bar形狀的對象便是約束了。Xcode 4的Interface Builder中不管你將UI控制器放在哪兒噩咪,它總是會給出有效的約束顾彰。理論上這聽起來是個好主意极阅,但是實踐起來,在Interface Builder中使用自動布局卻非常困難涨享。

幸運的是筋搏,Xcode5中已經(jīng)有所好轉(zhuǎn)。將button拖拽到畫布上之后并看不到T-bars形狀的東西:

同時在Document Outline面板中也沒用Constraints部分挡爵。得到結(jié)論:此時button上并沒有設置任何約束挣郭。

那這是如何運作的呢蕉汪?我們之前了解的自動布局總是需要足夠多的約束才能決定視圖的大小和位置革砸,但是現(xiàn)在我們這兒跟本沒有約束。確定這是一個完整的布局?

這這是Xcode5相對Xcode4來說最大的一個提升:再也不強制你總是有一個有效的布局蚂蕴。

注意:1.運行一個無效布局的程序是不明智的引镊,因為自動布局不能正確的計算需要將視圖放在哪兒。要么視圖的位置是不可預知的(約束不夠)除师,要么程序?qū)罎ⅲs束過多)。

2.Xcode4設法保證總是有足夠多正確的約束來創(chuàng)建一個有效的布局叹哭。不幸的是忍宋,它經(jīng)常會將你的約束替換為你并不想要的。這會令人很沮喪风罩,正是因為這個原因很多開發(fā)者放棄了自動布局糠排。

3.Xcode5中,當你編輯Storyboard時它允許你有不完整的布局超升,但它也會指出哪些地方你還需要修改入宦。使用Interface Builder創(chuàng)建的自動布局驅(qū)動用戶界面變得更有趣了哺徊,使用Xcode5也消耗更少的時間。

如果你根本不提供任何約束乾闰,Xcode自動分配一套默認的約束落追,正是我們所知的自動約束。它會在程序built的編譯時間中去完成這些事涯肩,而不是設計時間轿钠。當你設計你的用戶界面時,Xcode5中的自動布局為了不參與你的設計方法而努力工作病苗,這這是我們喜歡它的原因疗垛。

自動約束為你的視圖提供一個固定尺寸和位置。換句話說硫朦,視圖總是擁有跟你在storyboard中看到的一樣的坐標继谚。這是非常方便的,因為這就意味著你可以大量的忽視自動布局阵幸。你可以為那些擁有充分約束的控件不增加約束花履,只為那些需要特殊規(guī)則的視圖創(chuàng)建約束。

OK挚赊,讓我們玩一玩約束并看看他們能做什么」畋冢現(xiàn)在,按鈕是在左上角荠割,并且沒有約束妹卿。確認按鈕跟兩個拐角向?qū)Ь€對齊。

使用Editor\Pin菜單為按鈕增加兩個新的約束蔑鹦,看起來像這樣:

這是Leading Space to Superview和Top Space to Superview選項夺克。

所有的約束都會在Document Outline面板中列出來:

目前有兩個約束,一個是button和main view左邊緣的Horizontal Space約束嚎朽,一個是button和main view上邊緣的Vertical Space約束铺纽。這個關(guān)系通過約束描述起來便是:"button總是位于其父視圖左上角20點處。"

注意:這些其實都不是非常有用的約束哟忍,因為他們有相同的自動約束狡门。如果你總是想你的button相對于父視圖左上角,那么你還不如不提供任何約束锅很,讓Xcode為你做這些其馏。

現(xiàn)在拖動button并將它放到屏幕的右上角,再次和藍色向?qū)Ь€對齊:

哇哦爆安,這里發(fā)生了什么叛复?在Xcode4中這會破壞舊的約束并賦值一個基于藍色向?qū)Ь€的新約束,但是在Xcode5中button保留了現(xiàn)存的約束。但問題是button在Interface Builder中的大小和位置再也不和自動布局希望基于約束的大小和位置相符合了褐奥。這叫做錯位的視圖咖耘。(misplaced view)

運行程序。Button仍然會出現(xiàn)在屏幕的左上角:

當談到自動布局抖僵,橙色代表壞的鲤看。Interface Builder繪制兩個橙色方塊:一個是虛線邊框,一個是實線邊框耍群。虛線方塊是根據(jù)自動布局顯示視圖的frame义桂。實線方塊是根據(jù)你在屏幕上放置的視圖的frame。這兩個應該吻合的蹈垢,但是這里并沒有慷吊。

如何修改取決于你想要達到什么目的:

1.你想讓button附屬于屏幕左邊緣254點處嗎?在這種情況下你需要將現(xiàn)存的Horizontal Space約束變大234點曹抬。這正是橙色badge中"+234"的意思溉瓶。

2.你想讓button附屬于屏幕的右邊緣?那么你需要移除現(xiàn)有的約束并重新創(chuàng)建一個新的谤民。

刪除Horizontal Space約束堰酿。首先在畫布或Document Outline中選中,然后按鍵盤上的Delete鍵张足。

注意這次Vertical Space約束變橙色了触创。直到現(xiàn)在它都是藍色的。那一個約束并沒有任何錯誤为牍;它的意思是剩下的沒有足夠的約束決定button完整的位置哼绑。你任然需要在X軸方向增加一個約束。

Note:你可能會奇怪碉咆,為什么Xcode不為X軸方向自動增加一個約束抖韩。Xcode中的規(guī)則是:Xcode只為那些你沒有設置任何約束的對象創(chuàng)建自動約束。一旦你增加一個約束疫铜,你便是告訴Xcode你接管了這個視圖茂浮。Xcode將不再增加任何自動約束,并希望你為這個視圖增加需要的約束块攒。

選中button励稳,并選擇Editor\Pin|Trailing Space to Superview.這迫使在button右邊緣和屏幕右邊緣增加一個新的約束。關(guān)系表達如下:"button總是位于距離其父視圖右上角20點處囱井。"

運行程序并旋轉(zhuǎn)到landscape。注意button如何與屏幕右邊緣保持相同距離:

當你放置一個對立于向?qū)Ь€的button(或者任何其他視圖)并新建一個約束時趣避,你會得到一個根據(jù)"HIG"(Apple's iOS Human Interface Guidelines document)定義的標準大小的間隔約束庞呕。對于邊框來說,標準大小空間是20點。

現(xiàn)在將button向左拖拽一點:

由于視圖錯位住练,你得到了一個橙色虛線邊框地啰。我們假設這個button新位置的確是你想要的。創(chuàng)建完一個約束后做一些細微的調(diào)整是很常見的讲逛,但這卻會導致橙色方塊出現(xiàn)亏吝。一個修改方法就是移除約束并創(chuàng)建一個新的,但還有一個更簡單的解決方案盏混。

Editor菜單上有一個Resolve Auto Layout Issues子菜單蔚鸥。從這個菜單中,選中Update Constraints许赃。就我這個情況來說止喷,這會告訴Interface Builder需要將約束變大64點,像這樣:

很好混聊,T-bars又變藍了弹谁,布局是有效的。在Document Outline中句喜,你可以看到Horizontal Space約束不再有一個標準的間隔了:

到目前為止你已經(jīng)嘗試過了Horizontal Space和Vertical Space約束预愤。還有一個"center"約束。拖拽一個新的Button對象到畫布底部中心咳胃,根據(jù)向?qū)Ь€完好入位:

為了保持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遠離視圖底部(再一次使用標準間隔)金句。

運行程序并旋轉(zhuǎn)到橫屏模式檩赢。甚至在橫屏模式,button也保持在屏幕底部的中心:

這就是你表達的意思---這個button始終應該位于底部中心违寞。注意贞瞒,你根本不需要告訴Interface Builder按鈕的坐標是什么,除非你想將它固定在視圖上趁曼。

通過自動布局军浆,你再也不需要擔心視圖位置的精確坐標或視圖大小了。相反挡闰,自動布局會根據(jù)你設置的約束得到這兩個參數(shù)乒融。

你可以在button的Size inspector中看到這個經(jīng)典轉(zhuǎn)移掰盘,現(xiàn)在有了很大的不同:

如果不使用自動布局,輸入值到X赞季,Y愧捕,Width或Height字段將會改變選中視圖的位置和大小。使用自動布局后申钩,你仍然可以輸入新值到這些字段次绘,但是如果你已經(jīng)為視圖設置了約束,那這可能造成視圖錯位撒遣。你將不得不更新約束來匹配新值邮偎。

舉個例子,把button的寬度改為100愉舔,畫布會變成這樣:

Xcode4用Horizontal Space取代Center X Alignment約束钢猛,并且button上會產(chǎn)生一個新約束強制它的寬度為100 points。然而轩缤,Xcode5說命迈,"如果你想讓button寬度變?yōu)?00 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自己是知道自己有多寬瓢省。它根據(jù)自己的title text加上一些padding就行了。如果你為button設置一個背景圖片痊班,它也會考慮進去勤婚。

這正是我們熟悉的intrinsic content size。并不是所有的控制器都有這個涤伐,但大部分是(UILabel是一個例子)蛔六。如果一個視圖可以計算自己理想的大小荆永,那么你就不需要為它特別指定Width或Height約束了废亭,你將會在稍后看到更多相關(guān)內(nèi)容国章。

為了恢復button到最佳大小,首先我們需要移除Width約束豆村。然后選中button液兽,并從Editor菜單中選擇Size to Fit Content。這樣就能夠恢復button的固有的內(nèi)容尺寸了掌动。

孤掌難鳴

向?qū)Ь€不但出現(xiàn)在一個視圖和它的父視圖之間四啰,而且也會出現(xiàn)在相同層級的視圖之間。拖拽一個新的button到畫布上進行演示粗恢。如果你將這個button拖近其他對象柑晒,這時他們的向?qū)Ь€將會開始相互影響。

將新button放到之前一個button的后面完好入位:

這還有一些向?qū)摼€眷射。Interface Builder識別出這兩個button可以通過不同方式對齊—頂部匙赞,中心以及基線。

Xcode4會將這些顯著的向?qū)Ь€轉(zhuǎn)變成新的約束妖碉。但是在Xcode5中涌庭,如果你想讓這兩個button間有約束,你需要自己創(chuàng)建欧宜。之前你已經(jīng)使用過Editor\Pin菜單來創(chuàng)建這兩個視圖間的約束坐榆,但是還有一個更簡單的方式。

選中新的button并按住Ctrl拖拽到另一個button上冗茸,像這樣:

放開鼠標按鍵席镀,出現(xiàn)一個彈出框。選擇第一個選項夏漱,Horizontal Spacing豪诲。

這將會創(chuàng)建一個新的約束:

它是橙色的,這意味著這個button至少還需要另一個約束麻蹋。button的大小是知道的(使用intrinsic content size)跛溉,并且還有一個button在X軸上的約束。只剩下Y軸沒有約束了扮授。

這種缺失約束的情況是很容易確定的芳室,但是更復雜的設計可能就沒這么明顯了。幸運的是刹勃,你不再需要敏思苦想堪侯,Xcode已經(jīng)記錄并可以確切的告訴你缺少了什么。

在Document Outline中會有一個紅色的小箭頭荔仁,就在View Controller Scene后面伍宦。點擊這個箭頭便會看到所有Auto Layout問題:

我們將Y軸方向缺失的約束加進去芽死。按住Ctrl并向下拖拽新的button:

這次彈出菜單有不同的選項了。這次菜單的選項是基于上下文環(huán)境的—你在哪些視圖間拖拽以及鼠標移動的方向次洼。選擇Bottom Space to Bottom Layout关贵。

現(xiàn)在新button有一個位于屏幕底部的Vertical Space,也有一個跟其他button相關(guān)聯(lián)的Horizontal Space卖毁。雖然空間非常幸驹(只有8 points),T-bar可能不大容易看到亥啦,但它就在那里炭剪。

點擊Document Outline里面的Horizontal Space(8):

當你選中一個約束,它會高亮自己所屬的控制器翔脱。這個特別的約束位于兩個button之間奴拦。這個約束表達了:“不管第一個button在哪兒或多大,第二個button總是出現(xiàn)在第一個button的左邊”届吁。

選中黃色背景的button并輸入較長的label错妖,比如:“A longer label”。輸入完成后瓷产,button會為新的text改變大小站玄,并且另一個button會移開。

最終濒旦,它依附在第一個button的左邊緣株旷,這正是我們所期望的:

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

為新button設置一個綠色背景色,這樣就可以更容易看出它的范圍梯嗽。

因為你將兩個button對齊在一起齿尽,現(xiàn)在他們之間存在HIG推薦的8 points間隔。按住Ctrl在兩個button之間拖拽將這變?yōu)橐粋€約束灯节。從彈出菜單中選中Vertical Spacing循头。

Note:“HIG”是“iOS Human Interface Guidelines”的簡稱,包含Apple推薦的良好的用戶界面設計炎疆。任何iOS開發(fā)者都有必要讀一讀這個規(guī)范卡骂。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改變約束大小∮⒓耍現(xiàn)在兩個button更進一步的分開了,但是他們?nèi)稳皇沁B接在一起的:

運行程序并翻轉(zhuǎn)到landscape模式查看效果:

button必然會保持他們垂直方向的排列绍赛,但是水平方向就不了!原因很明顯:綠色button還沒有X軸方向的約束辑畦。

為綠色button增加一個到屏幕左邊緣的Horizontal Space并不能解決問題吗蚌。這樣的約束只會讓綠色按鈕總是保持在同一個X軸坐標,即便是在橫屏模式下纯出。這看起來感覺不大對蚯妇,所以你需要表述這樣一個目的:

“黃色button會一直水平居中,藍色button左邊緣會一直跟黃色button左邊緣對齊暂筝÷嵫裕”

你已經(jīng)為第一種情況創(chuàng)建了一個約束,但是第二個并沒有焕襟。Interface Builder為對齊顯示了向?qū)Ь€陨收,這樣你就可以將上面button一直拖拽到跟黃色左邊緣對齊的位置:

如果你也在垂直方向上拖拽button,這時button框架和Vertical Space約束之間就不能達到正確的距離了鸵赖。你在T-bar上將會看到橙色的badge:

如果發(fā)生這樣的情況务漩,簡單的使用方向鍵將button微調(diào)到位,直到badge消失它褪。

最終饵骨,按住Ctrl在兩個button間拖拽,從彈出菜單中選擇Left茫打。這會創(chuàng)建一個約束:“兩個視圖的左邊緣一直對齊”居触。換句話說,這兩個button一直會有相同的X軸坐標老赤。這時T-bars變成藍色了:

運行程序并旋轉(zhuǎn)到橫屏模式:

何去何從轮洋?

現(xiàn)在你已經(jīng)對自動布局進行了第一次嘗試,感覺怎么樣诗越?這可能需要一些時間習慣砖瞧,但是它能讓你的工作更加簡單,也會讓你的app更加靈活嚷狞。

想要學習更多的內(nèi)容块促?繼續(xù)閱讀第二部分吧荣堰,你將會繼續(xù)在Interface Builder中使用button進一步理解Auto Layout提供的多種可能性,以及你可能遇到的問題竭翠。

最重要的是振坚,你將會使用Auto Layout在一個真實的程序中創(chuàng)建一個逼真的布局。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末斋扰,一起剝皮案震驚了整個濱河市渡八,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌传货,老刑警劉巖屎鳍,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異问裕,居然都是意外死亡逮壁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門粮宛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窥淆,“玉大人,你說我怎么就攤上這事巍杈∮欠梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵筷畦,是天一觀的道長词裤。 經(jīng)常有香客問我,道長汁咏,這世上最難降的妖魔是什么亚斋? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮攘滩,結(jié)果婚禮上帅刊,老公的妹妹穿的比我還像新娘。我一直安慰自己漂问,他們只是感情好赖瞒,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蚤假,像睡著了一般栏饮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上磷仰,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天袍嬉,我揣著相機與錄音,去河邊找鬼。 笑死伺通,一個胖子當著我的面吹牛箍土,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播罐监,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吴藻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了弓柱?” 一聲冷哼從身側(cè)響起沟堡,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎矢空,沒想到半個月后航罗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡妇多,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年伤哺,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片者祖。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖绢彤,靈堂內(nèi)的尸體忽然破棺而出七问,到底是詐尸還是另有隱情,我是刑警寧澤茫舶,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布械巡,位于F島的核電站,受9級特大地震影響饶氏,放射性物質(zhì)發(fā)生泄漏讥耗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一疹启、第九天 我趴在偏房一處隱蔽的房頂上張望古程。 院中可真熱鬧,春花似錦喊崖、人聲如沸挣磨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茁裙。三九已至,卻和暖如春节仿,著一層夾襖步出監(jiān)牢的瞬間晤锥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工廊宪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留矾瘾,地道東北人女轿。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像霜威,于是被迫代替她去往敵國和親谈喳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

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