概念
約束優(yōu)先級
所有約束都有1-1000的優(yōu)先級。優(yōu)先級為1000的約束是必須的。其它約束都是可選的。
注意:不要強迫使用所有1000個優(yōu)先級值章姓。實際上,優(yōu)先級通常聚集在系統(tǒng)定義的低(250),中(500)凡伊,高(750)和必須(1000)周圍零渐。可能需要讓約束的優(yōu)先級比這些值高或低1-2點窗声,來幫助阻止綁定(teis)。如果優(yōu)先級遠(yuǎn)遠(yuǎn)超出這些值辜纲,可能需要重新檢查布局邏輯笨觅。
固有內(nèi)容尺寸(Intrinsic Content Size)
有些視圖根據(jù)當(dāng)前給定的內(nèi)容有個自然的尺寸。這個尺寸被稱為固有內(nèi)容尺寸(Intrinsic Content Size)
耕腾。
不是所有視圖都有固有內(nèi)容尺寸见剩。對于有固有內(nèi)容尺寸的視圖,它可以定義視圖的高度扫俺,寬度或者兩者都定義苍苞。下面的表格列出了一些例子(這里只標(biāo)注iOS的,mac OS已刪除)狼纬。
視圖 | 固有內(nèi)容尺寸 |
---|---|
UIView | 沒有固有內(nèi)容尺寸 |
UISlider | 只定義了寬度羹呵。 |
UILabel,UIbutton,UISwitch,UITextField | 同時定義了寬度和高度。 |
UITextView,UIImageView | 固有內(nèi)容尺寸可以改變疗琉。 |
Content hugging & Compression resistance
自動布局使用了一對約束來呈現(xiàn)一個視圖的每個維度冈欢。content hugging向內(nèi)抱緊視圖,使緊貼內(nèi)容(簡稱抱緊我)盈简。壓縮阻力(compression resistance)向外推視圖凑耻,使其不剪輯內(nèi)容(簡稱別擠我)。
Content hugging優(yōu)先級越高柠贤,抱的越緊香浩;compression resistance優(yōu)先級越高,壓縮阻力越大臼勉,內(nèi)容越不容易被剪輯邻吭。
下面舉兩個例子說明一下:
- 例1(Content hugging)
通常會有這樣一個功能,左側(cè)label宴霸,提示輸入名字镜盯,右側(cè)是一個textfield,用于輸入名字猖败,如下圖所示:
這時候我們希望name足夠小速缆,能顯示name足以,textfield則盡量拉伸恩闻。
這時候只需要name的Content hugging屬性優(yōu)先級大于textfield就可以了艺糜。
- 例2(compression resistance)
給一個label添加寬度為80的約束,如果label的文字超過80,那么顯示就會這樣:
因為compression resistance默認(rèn)優(yōu)先級為750破停,而高寬這些數(shù)據(jù)的優(yōu)先級默認(rèn)是required(即1000)翅楼。所以我們只要將寬度的約束優(yōu)先級修改一下,比750小即可真慢,比如749.這樣修改后毅臊,效果如下:
這樣應(yīng)該就能很好理解兩個屬性的意義了。
常見關(guān)系優(yōu)先級:
屬性或關(guān)系 | 優(yōu)先級 |
---|---|
equal | 1000 |
greater-than-or-equal | 1000 |
less-than-or-equal | 1000 |
Content hugging | 250 |
Compression resistance | 750 |
工具
Align工具
Align工具可以快速對齊布局中的項黑界。選擇想要對齊的項管嬉,然后單擊Align工具。界面生成器顯示一個彈出框視圖朗鸠,其中包括一些可能的對齊選項蚯撩。
Pin工具
Pin工具可以快速定義視圖相對于它鄰居的位置,或者快速定義視圖的尺寸烛占。選擇想要固定(pin)位置或尺寸的項胎挎,然后點擊Pin工具。界面生成器顯示一個彈出框視圖忆家,其中包括一些選項犹菇。
彈出框頂部區(qū)域可以固定選中項的開頭,頂部芽卿,結(jié)尾或底部邊緣到它最近的鄰居项栏。關(guān)聯(lián)的數(shù)字表示畫布中兩個項之間的當(dāng)前間隔〉攀可以輸入自定義的間隔沼沈,或者點擊三角形,設(shè)置它被約束到哪個視圖币厕,或者選擇標(biāo)準(zhǔn)間隔列另。Constrain to margins復(fù)選框決定約束使用父視圖的頁邊留白(margin)還是它的邊緣(edge)。
Resolve Auto Layout Issues工具
Resolve Auto Layout Issues工具提供了一些選項用來修復(fù)常見的自動布局問題旦装。菜單的上半部分只影響當(dāng)前選中的視圖页衙。下半部分選項影響場景中所有視圖。
可以使用這個工具更新視圖的框架(frame)阴绢,基于當(dāng)前的約束店乐,或者根據(jù)視圖在畫布中的當(dāng)前位置更新約束。還可以添加缺失的約束呻袭,清理約束眨八,或者重置視圖為界面生成器推薦的約束。
調(diào)試技巧
在自動布局過程中左电,出現(xiàn)錯誤是經(jīng)常的事情廉侧,自動布局中的錯誤主要分為三個類型:
- 不可滿足的(unsatisfiable)布局页响。布局沒有有效的解。更多信息請參考不可滿足的布局段誊。
- 有歧義的布局闰蚕。你的布局有兩個或多個可能的解。更多信息請參考有歧義的布局连舍。
- 邏輯錯誤没陡。布局邏輯中存在bug。更多信息請參考邏輯錯誤索赏。
調(diào)試方法:
查看控制臺的打印信息盼玄,有時候打印的信息比較多,不方便看参滴,添加標(biāo)識符强岸,是一個很好的方法锻弓。
高級自動布局
推遲的布局過程
自動布局安排一個布局過程在不久的將來取代直接更新受影響的view的frame砾赔。該推遲的過程更新布局的約束,然后計算視圖層次結(jié)構(gòu)中所有視圖的frame青灼。
可以通過調(diào)用setNeedsLayout方法或者setNeedsUpdateConstraints方法暴心,調(diào)度自己的推遲的布局過程。
推遲的布局過程實際涉及視圖層級結(jié)構(gòu)的兩個過程:
1.更新過程根據(jù)需要更新約束杂拨。
2.布局過程根據(jù)需要重新定位視圖的frame专普。
更新過程
系統(tǒng)遍歷視圖層級結(jié)構(gòu),并在所有視圖控制器上調(diào)用updateViewConstraints方法弹沽,在所有視圖上調(diào)用updateConstraints方法檀夹。你可以覆寫這些方法,來優(yōu)化約束的改變(查看批量改變)策橘。布局過程
系統(tǒng)再次遍歷視圖層級結(jié)構(gòu)炸渡,并在所有視圖控制器上調(diào)用viewWillLayoutSubviews方法,在所有視圖上調(diào)用layoutSubviews丽已。默認(rèn)情況下蚌堵,layoutSubviews方法使用自動布局引擎計算的矩形更新每個子視圖的frame。你可以覆寫這些方法來修改布局(查看自定義布局)沛婴。
批量改變
影響變化發(fā)生后吼畏,立即更新約束幾乎總是更干凈和容易。推遲這些改變到一個之后的方法會讓代碼復(fù)雜嘁灯,更難理解泻蚊。
然而,有些時候你可能基于性能原因丑婿,希望批量修改藕夫。只有在就地改變約束太慢孽糖,或者當(dāng)視圖做了很多多余的改變時,才應(yīng)該這么做毅贮。
要想批量改變办悟,在持有約束的視圖上調(diào)用setNeedsUpdateConstraints方法,而不是直接做出改變滩褥。然后病蛉,覆寫視圖的updateConstraints方法,來修改受影響的約束瑰煎。
提示:你的updateConstraints實現(xiàn)必須盡可能高效铺然。不要禁用所有約束,然后啟用你需要的酒甸。相反魄健,你的應(yīng)用程序必須有些方式來追蹤你的約束,并在每個更新過程中驗證它們插勤。只有變化的項需要改變沽瘦。在每一個更新過程中,你必須確保應(yīng)用程序的當(dāng)前狀態(tài)有合適的約束农尖。
總是在你實現(xiàn)的updateConstraints方法的最后一步調(diào)用父類的實現(xiàn)析恋。
不要在你的updateConstraints方法中調(diào)用setNeedsUpdateConstraints。調(diào)用setNeedsUpdateConstraints調(diào)度另一個更新過程盛卡,創(chuàng)建了一個反饋回路(feedback loop)助隧。