自動(dòng)布局出現(xiàn)以前的布局模式是基于UIView的frame屬性。
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 50, 60)];
[self.view addSubview:subView];
繪制效果如圖:
從最底層的view開(kāi)始進(jìn)行布局供鸠,在它的上面對(duì)應(yīng)的位置繪制子視圖,如此循環(huán)下去就可以得到所有視圖的位置陨闹。
這種布局方式的問(wèn)題就在于不能適應(yīng)不同尺寸的屏幕楞捂。對(duì)于同一個(gè)視圖V,假如希望V在4英寸的屏幕上的寬度為200趋厉,在5.5英寸的屏幕上顯示的為300寨闹,這種布局的模式就很難做到。因此在最開(kāi)始的時(shí)候君账,豎屏到橫屏的轉(zhuǎn)化通常需要繪制兩套布局繁堡。
自動(dòng)布局的原理
自動(dòng)布局的引入解決了不同屏幕尺寸的適配問(wèn)題。
自動(dòng)布局的過(guò)程實(shí)際上是通過(guò)對(duì)于給出的視圖之間的關(guān)系乡数,計(jì)算出各個(gè)視圖的位置的過(guò)程椭蹄。最終還是會(huì)轉(zhuǎn)化成原始的frame的方式來(lái)繪制到屏幕上去。所以自動(dòng)布局的關(guān)鍵有兩點(diǎn)净赴,一是你給出的描述是否能夠讓CPU計(jì)算出其最終的位置绳矩,而是你的描述是不是你最終想要的結(jié)果。對(duì)于第一點(diǎn)玖翅,可能出錯(cuò)的地方在于翼馆,你給出的視圖之間的關(guān)系本身是有沖突的或者給出的視圖之間的關(guān)系不足以完全計(jì)算出視圖的最終位置。
其實(shí)最原始的基于frame的布局也是描述視圖間的關(guān)系金度,子視圖相對(duì)于父視圖x方向上的位置应媚,y方向上的位置,寬度和長(zhǎng)度猜极。自動(dòng)布局在此基礎(chǔ)上擁有多種視圖間關(guān)系的描述中姜。并且很大的一個(gè)不同在于,自動(dòng)布局可以描述任何視圖之前的關(guān)系跟伏,而不僅僅限于子視圖與父視圖的關(guān)系丢胚。
自動(dòng)布局的約束
上面所說(shuō)的“關(guān)系”,在自動(dòng)布局中定義為約束(Constrains)酬姆。
約束可以由兩個(gè)視圖的屬性以及屬性之間的關(guān)聯(lián)決定。
自動(dòng)布局里奥溺,視圖中可以定義為約束的屬性包括:
top辞色,left (leading),bottom,right(trailing)相满,width层亿,length,centerX立美,centerY匿又,center,baseline
其中baseline是文字的基線建蹄,見(jiàn)下圖中的紅線
屬性之間的關(guān)聯(lián)關(guān)系包括:
相等碌更,大于,小于洞慎,大于等于痛单,小于等于,系數(shù)(multiplier)劲腿,偏移量(constant,offset)
一個(gè)約束可以描述為下圖:
注意的是除了center外的屬性都是代表位置(或者長(zhǎng)度寬度)的一個(gè)float類型的數(shù)字旭绒,center是centerX和centerY的集合。屬性乘以一個(gè)系數(shù)一般是一個(gè)float乘以系數(shù)焦人。
在自動(dòng)布局中挥吵,我們所要做的就是根據(jù)自己的需求描述出完整并且正確的約束。
完整的實(shí)例(來(lái)自Apple官方文檔):
1. // Vertical Constraints
2. Red.top = 1.0 * Superview.top + 20.0
3. Superview.bottom = 1.0 * Red.bottom + 20.0
4. Blue.top = 1.0 * Superview.top + 20.0
5. Superview.bottom = 1.0 * Blue.bottom + 20.0
6.
7. // Horizontal Constraints
8. Red.leading = 1.0 * Superview.leading + 20.0
9. Blue.leading = 1.0 * Red.trailing + 8.0
10. Superview.trailing = 1.0 * Blue.trailing + 20.0
11. Red.width = 1.0 * Blue.width + 0.0
其中約束2-5決定了垂直方向的布局花椭,8-11決定了水平方向的布局忽匈。
假設(shè)Superview為一個(gè)100*100的視圖,那么根據(jù)這幾個(gè)約束如何計(jì)算出Red和Blue的具體位置呢个从?
根據(jù)2脉幢,8這兩個(gè)約束可以決定Red的frame為(20,20嗦锐,width嫌松,height)
根據(jù)2,3這兩個(gè)約束可以決定Red的height為100-20-20 = 60奕污;
同理根據(jù)4萎羔,5可以決定Blue的height為60;
根據(jù)9碳默,可以得到 Blue.leading = 20 + Red.width + 8
加上10可以得到 20+Red.width+8+Blue.width+20 = 100
根據(jù)11贾陷,Red.width = Blue.width, 所以變成解方程:20+width+8+width+20 = 100, width = 26;
所以Red的frame為(20嘱根,20髓废,26,60)
Blue.leading = 20+26+8 = 54该抒,所以Blue的frame為(54,20,26,60)
那么如果給出的約束不正確會(huì)怎么樣呢?
假如給出的約束是自相矛盾的慌洪,像Blue.leading = 10, Blue.trailing=5這樣的約束,那么顯然系統(tǒng)就無(wú)法計(jì)算出正確的布局的了。
假設(shè)給出的約束少了冈爹,在上述例子中涌攻,缺少任何一個(gè)約束,系統(tǒng)都無(wú)法準(zhǔn)確計(jì)算出布局频伤。
所以恳谎,再?gòu)?qiáng)調(diào)一遍:在自動(dòng)布局中,我們所要做的就是根據(jù)自己的需求描述出完整并且正確的約束憋肖。 以便于系統(tǒng)自動(dòng)計(jì)算出各個(gè)視圖的frame因痛。