AutoLayout的自適應(yīng)大小
問(wèn)題
近日開(kāi)發(fā)遇到一個(gè)需求.如下圖:

綠色view為SnapKit代碼布局的自定義view,高度固定,寬度根據(jù)子視圖內(nèi)容長(zhǎng)度而定.右側(cè)label與綠色view間隔為10.
如果不設(shè)定綠色view的寬度約束或距父視圖右側(cè)約束,xib就會(huì)報(bào)錯(cuò),而其寬度又是根據(jù)子視圖的內(nèi)容決定的,同時(shí)導(dǎo)致右側(cè)label的位置也無(wú)法確定.
常用的解決方案可能是先添加上寬度約束,然后在代碼里計(jì)算綠色view的寬度并更新寬度約束的值.
那么,有什么更好更簡(jiǎn)單的解決方案呢?
可不可以像UILabel,UIButton,UIImageView這些組件,不指定寬度和高度,自動(dòng)根據(jù)內(nèi)容計(jì)算寬和高呢?
解決方案
其實(shí)方法很簡(jiǎn)單,只需要按照下圖操作即可:

將Intrinsic Size改為Placeholder.根據(jù)下方描述,此處設(shè)置的intrinsic content size只會(huì)在IB中顯示,運(yùn)行時(shí)視圖并沒(méi)有此處設(shè)置的intrinsic content size.
注意: view的子視圖需要添加距其上下左右的約束,不設(shè)置Autolayout無(wú)法根據(jù)子視圖內(nèi)容自適應(yīng)寬高
What is intrinsic content size
顧名思義,IntrinsicContentSize-固有內(nèi)容尺寸.即根據(jù)內(nèi)容計(jì)算size,UILabel,UIButton,UIImageView等控件就是系統(tǒng)內(nèi)部重寫(xiě)了-(CGSize)intrinsicContentSize:方法來(lái)實(shí)現(xiàn)自適應(yīng)size的.當(dāng)view的子視圖為這些實(shí)現(xiàn)了IntrinsicContentSize的控件時(shí),加上我們添加的固定的left,right,top,bottom約束時(shí),Autolayout就可以根據(jù)內(nèi)容自適應(yīng)view的大小了.
回到圖1,如果綠色view在父視圖中非autolayout布局,而是frame布局時(shí),又怎么確定其寬高呢?右側(cè)label又怎么布局呢?
不還是需要根據(jù)內(nèi)容,計(jì)算綠色view的子視圖的寬度并相加,再加上子視圖的間隔嗎?
系統(tǒng)在 iOS6 就提供的 API:-systemLayoutSizeFittingSize:,約束添加正確的話,可以直接調(diào)用就獲取對(duì)應(yīng)的view的寬高,然后更新view的寬高就行
拓展
圖1中如果綠色view過(guò)長(zhǎng),會(huì)將右側(cè)label直接擠掉,如圖所示:

此時(shí)就需要用到Content Hugging/Content Compression Resistance了.
Content Hugging/Content Compression Resistance都可以設(shè)置寬度和高度的優(yōu)先級(jí).值越大,優(yōu)先級(jí)越高.
Content Hugging抗拉伸約束,如果控件的此屬性優(yōu)先級(jí)比另一個(gè)控件此屬性優(yōu)先級(jí)高的話,那么這個(gè)控件就保持不變,另一個(gè)可以在需要拉伸的時(shí)候拉伸.
Content Compression Resistance抗壓縮約束,如果控件的此屬性優(yōu)先級(jí)比另一個(gè)控件此屬性優(yōu)先級(jí)高的話,那么這個(gè)控件就保持不變,另一個(gè)可以在需要壓縮的時(shí)候壓縮.
設(shè)置方式:
IB:

代碼:
[view setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
[view setContentCompressionResistancePriority: UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
如果不想要label被擠掉,只需要將其Content Compression Resistance優(yōu)先級(jí)設(shè)置的比綠色view高就行,當(dāng)綠色view過(guò)長(zhǎng),會(huì)壓縮綠色view的寬度,依然完整顯示右側(cè)label.