有關於Autolayout中的 Intrinsic Content Size、Content Hugging Priority、Content Compression Resistance Priority、Constraint Priority
在使用 Autolayout 的過程中,難免都會遇到有關於諸如此類的問題,法蘭克一次整理了這四個相關的說明和範例,讓我們一次來釐清它們吧!
intrinsic content size(固定內容尺寸)
有些元件的 Size 是固定的,所謂固定並不是說不能去調整它,而是說可以不需要特別去定義它,Autolayout 會根據其文字內容自動決定它們的固定 Size。例如:Label 和 Button 皆是此類的元件。以下使用兩個圖來說明之。
從 Storyboard 拉了一個「Label」並只定義了水平和垂直置中的約束,此時「不會」有衝突發生(左圖)。反之「ImageView」則會「有」衝突發生(右圖)。
content hugging priority(內容緊致優先權)
優先權「愈高愈緊致」,也就是愈不容易被拉寬拉高的意思啦,預設值 251。如下圖 Label2 優先權 > Label1。也可以把這個屬性想像成 View(Label) 在 SuperView 中佔用的空間大小。
若是有設定 constraint,則在 size Inspector 會顯示該屬性並可重新設置它,而 content hugging priority 並非全局的,而是僅僅跟該 SubView 裡的所有元件相比的。例如法蘭克將這兩個 Label 放在一個 StackView 裡,則 content hugging priority 的屬性設置僅僅只是它們兩個相比罷了。
以下就開始試著來製造一個 content hugging priority 的衝突,並試著解決它:
如同畫面,拉兩個 Label 並將其嵌入 Stack View,並設置 Stack View 的約束,固定高度 = 50、垂直置中、寬度依照瑩幕的比例縮放
備註:***請注意 Label 的寬度不能設為固定,否則是製造不出 content hugging priority 的衝突的***。
很明顯示的 Xcode 提示我們有 content hugging priority 的衝突發生,必須調整 Label1 的 Content Hugging Priority Horizontal 為 250 或調整 Label2 的 Content Hugging Priority Horizontal 為 252,而實際上我們只要調整其中一項即可,因為預設為 251,我們只要清楚明白跟 Autolayout 說哪個優先即可。
切換到 Label1 的 size Inspector 並調整 Content Hugging Priority Horizontal 為 252,此時 Label1 的優先權 > Label2,白話一點就是 Label1 要比 Label2 更緊致啦,結果如下:
反之調整 Label2 的 Content Hugging Priority Horizontal 為 252 結果如下(Label1 記得調回251):
content compression resistance priority(內容壓縮抵抗優先權)
優先權「愈高愈不容易被壓縮」,預設值 750。如上一個範例當內容文字不會互相擠壓的時侯,才會有 content hugging priority 的問題發生;反之文字多到會互相擠壓時則不會有,因為空間都不夠了還談什麼緊致度阿!!!只會有 content compression resistance priority 的問題發生!如下圖 Label2 優先權 > Label1(我的內容非常長非常長非常長非常長非常長非常長非常長非常長),當寬度不足以放下所有的文字時,Autolayout 會使用「…」替代。
若是有設定 constraint,則在 size Inspector 會顯示該屬性並可重新設置它,而 content compression resistance priority 並非全局的,而是僅僅跟該 SubView 裡的所有元件相比的。例如法蘭克將這兩個 Label 放在一個 StackView 裡,則 content compression resistance priority 的屬性設置僅僅只是它們兩個相比罷了。
以下就開始試著來製造一個 content compression resistance priority 的衝突,並試著解決它:
畫面承上一個範例,這邊只需要將 Label1 的文字改成「我的內容非常長非常長非常長非常長非常長非常長非常長」即會有此衝突發生。
很明顯示的 Xcode 提示我們有 content compression resistance priority 的衝突發生,必須調整 Label2 的 content compression resistance priority Horizontal 為 749,而實際上並不一定要是 749,只要比 Label1 的低即可,因為預設為 750,我們只要清楚明白跟 Autolayout 說哪個優先即可。
試著將 Labe2 調整為 749,此時 Label2 的 size 被壓成 (0, 0) 了
反之若不想 Label2 被壓縮,則可以調高 Label2 的 content compression resistance priority horizontal
備註:在實務上通常會把欄位名稱的「內容緊致優先權」、「內容壓縮抵抗優先權」設的比較高,因為總不能讓使用者連自己在輸入什麼都不知道吧!
constraint priority(約束優先權)
一般的約束其實也是有優先權的,預設是最高的 1000
以下使用一個範例來說明之:
如同畫面,拉一個 Label 文字內容設置「我的內容非常長非長常非長常非長常非長常非長常」,固定寬度 = 50、水平置中、垂直置中
如上圖所示,文字內容被壓縮了,原因是因為 content compression resistance priority horizontal(預設750) < width constraint priority(預設1000),此時試著只要調整 width constraint priority < 750 會有意想不到的結果喔