編者按:
這是一篇說(shuō)明文, 比較適合當(dāng)作茶余飯后修身養(yǎng)性的點(diǎn)心小品, 對(duì)于如何解決具體的布局及約束問題,沒有立竿見影的療效屑咳。
一般來(lái)說(shuō),iOS開發(fā)中,UI/UE等用戶界面及交互相關(guān)的開發(fā)會(huì)占用掉項(xiàng)目中的很大一塊時(shí)間, 那些不痛不癢的類似于CRUD的業(yè)務(wù)邏輯, 反而用時(shí)較少宪拥。(邏輯嚴(yán)密的復(fù)雜系統(tǒng)例外)
如果遇見對(duì)界面還原度要求特別的高的產(chǎn)品經(jīng)理外傅、設(shè)計(jì)師或老板薄声, 在UI/UE及用戶交互上花費(fèi)的時(shí)間還會(huì)更多锡垄。
在高仿設(shè)計(jì)稿的過程中岛心,遇見約束沖突是難免的来破。
很數(shù)時(shí)候,控制臺(tái)雖然顯示了很多約束沖突的警告,但是在真機(jī)上忘古,貌似一切都很正常.
系統(tǒng)似乎已經(jīng)自動(dòng)的幫助我們break掉那些有歧義的或?qū)е聸_突的約束徘禁。
雖然在大部分情況下,系統(tǒng)對(duì)約束沖突的自動(dòng)處理貌似都是有效的髓堪,但是那些討厭的警告時(shí)不時(shí)的在控制臺(tái)打印出來(lái)送朱,還是會(huì)讓人心煩意亂。特別是當(dāng)面對(duì)來(lái)自leader或同事的質(zhì)疑時(shí)干旁。
必須熟練使用Auto Layout驶沼,并快速解決約束沖突
為真正困難的工作節(jié)省寶貴的時(shí)間!
這個(gè)公式就是Auto Layout 之靈魂
這張圖來(lái)自蘋果的官方網(wǎng)站,地址:
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/AnatomyofaConstraint.html#//apple_ref/doc/uid/TP40010853-CH9-SW1
這里有關(guān)于如何使用Autolayout的官方教程
先熱個(gè)身疤孕,對(duì)Auto Layoutyou 有個(gè)直觀的認(rèn)識(shí)
使用xib或者storyboard來(lái)繪制界面
使用Interface Builder畫布查找和解決視圖或視圖的問題商乎。 使用大綱視圖查找并解決視圖控制器的所有問題。
在畫布上查找自動(dòng)布局問題
官網(wǎng)的原始鏈接地址:
https://help.apple.com/xcode/mac/8.0/#/devc276f21a7
-
在Interface Builder畫布上祭阀,選擇所需的視圖鹉戚。 警告限制顯示為橙色。 有錯(cuò)誤的約束以紅色顯示专控。
在下面的屏幕截圖中抹凳,視圖2中紅色表示錯(cuò)誤。 視圖3中橙色表示警告伦腐。
在大綱視圖中查找自動(dòng)布局問題
-
在大綱視圖中赢底,單擊約束問題指示器。
大綱視圖顯示視圖控制器的所有自動(dòng)布局警告和錯(cuò)誤的分類列表。 警告或錯(cuò)誤的每個(gè)類別都可能有多個(gè)問題幸冻。
使用Resolve Auto Layout Issues工具解決問題
1粹庞、在Interface Builder畫布上,選擇一個(gè)或多個(gè)具有自動(dòng)布局問題的視圖洽损。
2庞溜、在畫布底部,單擊布局欄中的解決自動(dòng)布局問題工具按鈕碑定。
3流码、在解決自動(dòng)布局問題彈出窗口中,選擇所需的選項(xiàng)延刘。
使用大綱視圖“自動(dòng)布局問題”詳細(xì)信息面板解決問題
- 在大綱視圖中漫试,導(dǎo)航到視圖控制器的自動(dòng)布局警告列表,然后單擊錯(cuò)誤或警告以查看帶有建議解決方案的彈窗碘赖。
以下屏幕截圖顯示了Auto Layout錯(cuò)誤的解決方案彈窗示例驾荣。 唯一的選擇是應(yīng)用建議的解決方案或取消修復(fù)。
通常有更多的選擇來(lái)修復(fù)修正錯(cuò)誤的警告普泡。 以下屏幕截圖顯示了警告的解決方案彈出窗口秘车。 修復(fù)警告需要三個(gè)步驟:
- 選擇一個(gè)解決方案
- 選擇將解決方案應(yīng)用于具有警告的視圖或視圖及其所有同級(jí)視圖
- 應(yīng)用該方案
For more help on debugging Auto Layout issues, see Debugging Auto Layout in Auto Layout Guide.
你會(huì)發(fā)現(xiàn)Auto Layout經(jīng)常提供多種方法來(lái)解決同樣的問題。 理想情況下劫哼,您應(yīng)該選擇最能夠清楚描述您的意圖的解決方案。 不同的開發(fā)人員對(duì)于某種解決方案是否最優(yōu)很難達(dá)成一致割笙。 所以权烧,保持一致性要?jiǎng)儆谡_性。 如果您選擇一種方法并始終堅(jiān)持伤溉,您將會(huì)遇到更少的問題般码。 例如,蘋果的指南中建議使用以下方法:
- 將multipliers設(shè)置成整數(shù)比設(shè)置成分?jǐn)?shù)更好一些乱顾。
- 正常數(shù)比負(fù)常數(shù)更好一些板祝。
- 只要有可能,視圖應(yīng)按布局順序顯示:從左往右走净,從上到下券时。
Constraint Priorities 約束的優(yōu)先級(jí)
下面的例子中,有三個(gè)使用Auto Layout的例子伏伯,這三個(gè)例子都是正確的布局橘洞,并且如果僅就本層級(jí)的視圖來(lái)說(shuō),均能夠?qū)崿F(xiàn)相同的效果说搅。
但是如果當(dāng)他們的superView的寬度發(fā)生變化時(shí)炸枣,這三種布局方式產(chǎn)生的效果將有很大的不同。
這也就意味著在進(jìn)行多機(jī)型適配或旋轉(zhuǎn)時(shí), 有可能本來(lái)看上去很完美的布局會(huì)變得不正確适肠。
默認(rèn)情況下霍衫,約束的優(yōu)先級(jí)別為required。 Auto Layout必須計(jì)算滿足所有約束的解決方案侯养。如果算不出敦跌,則產(chǎn)生一個(gè)錯(cuò)誤。 Auto Layout把不可滿足的約束信息打印到控制臺(tái)沸毁,并選擇一個(gè)約束來(lái)打破峰髓。然后重新計(jì)算滿足所有約束的解決方案。 For more information, see Unsatisfiable Layouts.
你可以創(chuàng)建optional constraints(可選約束). 所有的約束都有一個(gè)從1-1000的優(yōu)先級(jí)息尺;1000表示優(yōu)先級(jí)是required級(jí)別的(即最高級(jí))携兵。 其他1-999的級(jí)別都是可選約束;
在計(jì)算解決方案時(shí)搂誉,自動(dòng)布局試圖以優(yōu)先順序從最高到最低滿足所有約束徐紧。如果它不能滿足可選約束,則跳過該約束炭懊,并繼續(xù)到下一個(gè)約束并级。
即使可選約束不能滿足,它仍然可以影響布局侮腹。 如果在跳過約束后布局中存在任何不明確的地方嘲碧,系統(tǒng)會(huì)選擇最接近約束的解決方案。 通過這種方式父阻,這些有問題的約束也能夠達(dá)到一定的“約束”效果愈涩;
可選的制約因素和不平等往往是相輔相成的。 例如加矛,在下面的例子中(Listing 3-4)履婉,您可以為這兩個(gè)不等式提供不同的優(yōu)先級(jí)。 可能需要大于或等于關(guān)系(優(yōu)先級(jí)為1000)斟览,小于或等于關(guān)系的優(yōu)先級(jí)較低(優(yōu)先級(jí)為250)毁腿。 這意味著藍(lán)色視圖離紅色不能超過8.0點(diǎn)。 但是苛茂,其他限制可能會(huì)將它拉遠(yuǎn)已烤。 盡管如此,可選約束會(huì)將藍(lán)色視圖拉向紅色視圖妓羊,以確保它盡可能接近8.0點(diǎn)間距草戈,同時(shí)考慮到布局中的其他約束條件。
Listing 3-4Replacing a single equal relationship with two inequalities
// A single equal relationship
Blue.leading = 1.0 * Red.trailing + 8.0
// Can be replaced with two inequality relationships
Blue.leading >= 1.0 * Red.trailing + 8.0
Blue.leading <= 1.0 * Red.trailing + 8.0
系統(tǒng)并不會(huì)要求所有的約束優(yōu)先級(jí)都必須設(shè)置為1000(required)侍瑟,你應(yīng)當(dāng)根據(jù)實(shí)際的需要來(lái)進(jìn)行設(shè)置唐片;
Intrinsic Content Size
這個(gè)概念很重要丙猬!在布局時(shí)如果處理不當(dāng),將會(huì)個(gè)你帶來(lái)很多麻煩费韭。
根據(jù)當(dāng)前內(nèi)容茧球,某些視圖具有自然(也可以理解為具有自身的、內(nèi)在的星持、本身具有的....)大小抢埋。 這被稱為它們的固有內(nèi)容大小。
例如督暂,按鈕的內(nèi)在內(nèi)容大小是其標(biāo)題的大小加上一個(gè)小的余量揪垄。
并非所有視圖都具有內(nèi)在內(nèi)容大小。 對(duì)于這樣的視圖逻翁,內(nèi)在內(nèi)容大小可以定義視圖的高度饥努,寬度或兩者。 表3-1列出了一些示例八回。
Table 3-1 Intrinsic content size for common controls
下面這個(gè)表格請(qǐng)牢記酷愧,有事半功倍的效果###
View | Intrinsic content size |
---|---|
UIView and NSView | No intrinsic content size. |
Sliders | Defines only the width (iOS). Defines the width, the height, or both—depending on the slider’s type (OS X). |
Labels, buttons, switches, and text fields | Defines both the height and the width. |
Text views and image views | Intrinsic content size can vary. |
內(nèi)在內(nèi)容大小基于視圖的當(dāng)前內(nèi)容缠诅。 標(biāo)簽或按鈕的內(nèi)在內(nèi)容大小基于顯示的文本量和使用的字體管引。 對(duì)于其他視圖士败,內(nèi)在內(nèi)容的大小更加復(fù)雜。 例如褥伴,空?qǐng)D像視圖不具有內(nèi)在內(nèi)容大小。 但是,只要添加圖像邦投,其內(nèi)在內(nèi)容大小就會(huì)設(shè)置為圖像的大小伤锚。
文本視圖的內(nèi)容內(nèi)容大小因內(nèi)容、是否啟用滾動(dòng)以及應(yīng)用于視圖的其他約束而異志衣。
例如,啟用滾動(dòng)功能后狞洋,該視圖不具有固有內(nèi)容大小绿店。
在禁用滾動(dòng)的情況下庐橙,默認(rèn)情況下視圖的內(nèi)在內(nèi)容大小是基于文本的大小計(jì)算的借嗽,沒有任何換行恶导。
例如,如果文本中沒有“回車”(return)邦泄,它將計(jì)算將內(nèi)容布置為單行文本所需的高度和寬度裂垦。 如果添加約束來(lái)指定視圖的寬度,則內(nèi)在內(nèi)容大小將定義顯示文本寬度所需的高度包蓝。
Auto Layout(自動(dòng)布局)使用每個(gè)維度的一對(duì)約束來(lái)表示視圖的內(nèi)在內(nèi)容大小(intrinsic content)企量。
內(nèi)容擁抱 (content hugging) 將內(nèi)部視圖拉向內(nèi)部届巩,使其適合周圍的內(nèi)容硅瞧。
壓縮阻力 (compression resistance ) 將視圖向外推腕唧,以便它不剪裁內(nèi)容瘾英。
這些約束是使用列表3-5中顯示的不等式定義的缺谴。
這里,IntrinsicHeight和IntrinsicWidth常量表示視圖內(nèi)在內(nèi)容大小的高度和寬度值膀曾。
Listing 3-5Compression-Resistance and Content-Hugging equations
// Compression Resistance 不能再比 intrinsic size 更小了
View.height >= 0.0 * NotAnAttribute + IntrinsicHeight
View.width >= 0.0 * NotAnAttribute + IntrinsicWidth
// Content Hugging 不能再比 intrinsic size 更大了
View.height <= 0.0 * NotAnAttribute + IntrinsicHeight
View.width <= 0.0 * NotAnAttribute + IntrinsicWidth
每個(gè)約束都可以有其自己的優(yōu)先級(jí)阳啥。
默認(rèn)情況下,視圖對(duì)其內(nèi)容擁抱Content Hugging 使用250優(yōu)先級(jí)斩狱,對(duì)于其壓縮抵抗Compression Resistance 優(yōu)先使用750喊废。
因此,拉伸視圖比縮小視圖更容易工闺。 對(duì)于大多數(shù)控制瓣蛀,這是所需的行為。
例如叠殷,您可以安全地拉伸大于其內(nèi)在內(nèi)容 intrinsic size 大小的按鈕;
然而诈皿,如果你縮小它的內(nèi)容稽亏,它的內(nèi)容可能會(huì)被剪輯掉。 請(qǐng)注意胖腾,Interface Builder可能會(huì)偶爾修改這些優(yōu)先級(jí)來(lái)幫助阻止關(guān)系瘪松。 有關(guān)更多信息,請(qǐng)參閱設(shè)置內(nèi)容擁抱和壓縮優(yōu)先級(jí)记罚。
相信我壳嚎,這個(gè)東西很重要诬辈!
如果你的按鈕或文本被莫名的剪裁掉兩個(gè)字荐吉,相信測(cè)試、產(chǎn)品經(jīng)理穿撮、運(yùn)營(yíng)悦穿、老板、用戶以及你自己礁扮,都不會(huì)放過你的瞬沦。
只要有可能,請(qǐng)?jiān)诓季种惺褂靡晥D的內(nèi)在內(nèi)容大小僚焦。 它可以讓您的布局動(dòng)態(tài)適應(yīng)視圖內(nèi)容的變化曙痘。 它還減少了創(chuàng)建非歧義边坤,非沖突布局所需的約束數(shù)量,但您需要管理視圖的內(nèi)容擁抱和抗壓縮(CHCR)優(yōu)先級(jí)罢洲。 以下是處理內(nèi)在內(nèi)容大小的一些準(zhǔn)則:
在擴(kuò)展一系列視圖以填充空間時(shí)文黎,如果所有視圖具有相同的內(nèi)容擁抱優(yōu)先級(jí)耸峭,則布局不明確。 自動(dòng)布局不知道應(yīng)該拉伸哪個(gè)視圖院究。
一個(gè)常見的例子是標(biāo)簽和文本字段對(duì)本涕。 通常情況下菩颖,您希望文本字段進(jìn)行拉伸以填充額外空間,同時(shí)標(biāo)簽保持其固有內(nèi)容大小放祟。 為確保這一點(diǎn),請(qǐng)確保文本字段的水平內(nèi)容擁抱優(yōu)先級(jí)低于標(biāo)簽鞋喇。
實(shí)際上眉撵,這個(gè)例子非常常見执桌,Interface Builder會(huì)自動(dòng)為您處理它,將所有標(biāo)簽的內(nèi)容擁抱優(yōu)先級(jí)設(shè)置為251.如果以編程方式創(chuàng)建布局伴逸,則需要自己修改內(nèi)容擁抱優(yōu)先級(jí)膘壶。當(dāng)不可見背景(如按鈕或標(biāo)簽)的視圖意外伸展超出其內(nèi)在內(nèi)容大小時(shí),通常會(huì)出現(xiàn)奇怪和意外的布局顷锰。 實(shí)際問題可能并不明顯官紫,因?yàn)槲谋局怀霈F(xiàn)在錯(cuò)誤的位置州藕。 為了防止不必要的拉伸,增加內(nèi)容擁抱優(yōu)先級(jí)床玻。
基線約束僅適用于處于內(nèi)在內(nèi)容高度的視圖锈死。 如果視圖被垂直拉伸或壓縮,則基線約束不再正確對(duì)齊其屏。
一些視圖缨该,如switches,應(yīng)始終以其固有內(nèi)容大小顯示。 根據(jù)需要增加他們的CHCR優(yōu)先級(jí)以防止拉伸或壓縮。避免將View的CHCR屬性設(shè)置為required汗盘。 通常情況下询一,視圖大小錯(cuò)誤比約束沖突更好健蕊。 如果視圖始終應(yīng)該是其內(nèi)在內(nèi)容大小,請(qǐng)考慮使用非常高的優(yōu)先級(jí)(999)晴及。 這種方法通车招浚可以保持視圖不被拉伸或壓縮势木,但仍然提供緊急壓力閥,以防萬(wàn)一您的視圖顯示在大于或小于預(yù)期的環(huán)境中溯壶。
這段說(shuō)明很拗口甫男,很難從字面意思就能體會(huì)到其中的要義建瘫。
再多的說(shuō)明也沒有自己做例子來(lái)的真切吏廉。
Intrinsic Content Size Versus Fitting Size 固有內(nèi)容大小與適合大小
內(nèi)在內(nèi)容大小作為自動(dòng)布局的輸入效扫。 當(dāng)視圖具有內(nèi)在內(nèi)容大小時(shí)菌仁,系統(tǒng)會(huì)生成約束來(lái)表示該大小静暂,并使用約束來(lái)計(jì)算布局。
另一方面疟赊,The fitting size(適配尺寸)是自動(dòng)布局引擎的輸出峡碉。 它是根據(jù)視圖的約束為視圖計(jì)算的大小鲫寄。 如果視圖使用“自動(dòng)布局”布局其子視圖,則系統(tǒng)可能會(huì)根據(jù)視圖的內(nèi)容來(lái)計(jì)算視圖的fitting size(適配尺寸)大小戳玫。
堆棧視圖 stack view 就是一個(gè)很好的例子未斑。 除了任何其他限制蜡秽,系統(tǒng)都會(huì)根據(jù)其內(nèi)容和屬性計(jì)算堆棧視圖stack view的大小。 在許多方面肌似,堆棧視圖stack view的行為就好像它具有內(nèi)在內(nèi)容大兴咄摺:您可以使用僅一個(gè)垂直和一個(gè)水平約束來(lái)定義其位置來(lái)創(chuàng)建有效的布局睬澡。 但其大小是通過自動(dòng)布局計(jì)算的 - 它不是自動(dòng)布局的輸入。 設(shè)置堆棧視圖的CHCR(內(nèi)容擁抱和抗壓縮)優(yōu)先級(jí)不起作用斗躏,因?yàn)槎褩R晥D沒有固有內(nèi)容大小啄糙。
If you need to adjust the stack view’s fitting size relative to items outside the stack view, either create explicit constraints to capture those relationships or modify the CHCR priorities of the stack’s contents relative to the items outside the stack.
如果您需要相對(duì)于堆棧視圖外的元素調(diào)整堆棧視圖的控件大性浦伞(fitting size)静陈,請(qǐng)創(chuàng)建明確的約束來(lái)描述這些關(guān)系诞丽,或者修改堆棧內(nèi)容相對(duì)于堆棧外項(xiàng)目的CHCR(內(nèi)容擁抱和抗壓縮)優(yōu)先級(jí)僧免。
這段說(shuō)明真的很拗口捏浊,很難從字面意思就能體會(huì)到其中的要義呛伴。
再多的說(shuō)明也沒有自己做例子來(lái)的真切谒所。
在Interface Builder中使用約束
在Interface Builder中劣领,有三種主要的方式來(lái)設(shè)置Auto Layout約束:
(1)使用control-drag (按住control,鼠標(biāo)點(diǎn)擊控件然后拖拽)奕锌,
(2)你可以使用Pin和Align工具(Pin用于確定位置惊暴,Align用于對(duì)齊控件)趁桃;
(3)讓Interface Builder來(lái)設(shè)置約束卫病,然后再編輯或修改。
三種方式各有優(yōu)劣益咬,很多開發(fā)者都只是更加喜歡其中的某一個(gè)方式帜平,而三種方式都熟練掌握可以讓你在工作中更加得心應(yīng)手裆甩。
Control-Dragging Constraints
To create a constraint between two views, Control-click one of the views and drag to the other.
When you release the mouse, Interface Builder displays a HUD menu with a list of possible constraints.
根據(jù)你正在進(jìn)行設(shè)置約束的控件及拖動(dòng)方向淑掌,Interface Builder會(huì)自動(dòng)列出一些約束設(shè)置項(xiàng)。
如果是水平拖動(dòng)媒殉,彈出菜單中的選項(xiàng)中會(huì)有一個(gè)用于設(shè)置橫向間距的“horizontal spacing”和一個(gè)垂直居中對(duì)齊的選項(xiàng)(Center Vertically)摔敛。
如果是垂直拖動(dòng)马昙,會(huì)看到"vertical spacing"和橫向居中對(duì)齊的選項(xiàng)。
這兩種拖動(dòng)還包括其他選項(xiàng)(例如設(shè)置控件的相對(duì)尺寸)