本篇博客的內容也不算太復雜,算是AutoLayout的一些高級的用法。本篇博客我們主要通過一些示例來看一下AutoLayout中的Content Hugging Priority以及Content Compression Resistance Priority這兩個優先級。下方我們先來簡單的看一下這兩個優先級的涵義:
-
Content Hugging Priority:直譯成中文就是“ 內容擁抱優先級”,從字面意思上來看就是兩個視圖,誰的“內容擁抱優先級”高,誰就優先環繞其內容。稍后我們會根據一些示例進行介紹。
-
Content Compression Resistance Priority:該優先級直譯成中文就是“ 內容壓縮阻力優先級”。也就是視圖的“內容壓縮阻力優先級”越大,那么該視圖中的內容越難被壓縮。而該優先級小的視圖,則內容優先被壓縮。稍后我們也會通過相應的實例來看一下這個優先級的具體表現。
接下來我們就通過相應的實例來看一下這兩個優先級的使用場景以及作用。
一、總述
首先在第一部分我們先來整體的看一下Content Hugging Priority與Content Compression Resistance Priority這兩個AutoLayout的優先級屬性。這兩個屬性是可以在Storyboard中直接設置的,選中要設置的控件,在右邊約束一欄里邊就有Content Hugging Priority以及Content Compression Resistance Priority的設置地方。Content Hugging Priority的水平和豎直方向的默認值都是250,而Content Compression Resistance Priority的水平和豎直的默認值是750。我們可以在此對該值進行設置。
當然,在代碼中也是可以設置這兩個代碼的優先級的。下方是使用代碼的方式為我們的控件設置相應的優先級並且我們可以獲取到相應優先級的值。具體代碼如下所示:
二、Content Hugging Priority
接下來我們就來結合實例來看一下Content Hugging Priority的使用場景以及使用方式。
假如我們有一個需求,需要兩個Label並列顯示,我們暫且稱之為Label1和Label2。Label1和Label2中的顯示內容是從網絡獲取的,並且內容長度不定。我們要求優先顯示Label1。也就是說以Label1的寬度為准,不過Label1會有一個最大寬度,當Label1顯示到最大寬度時,Label1的內容會被壓縮,剩下的部分顯示Label2。當然,當Label1沒有顯示到最大值時,剩下的部分仍然顯示Label2。Label2顯示不全的也會被壓縮。
接下來我們按照上述的描述添加相應的約束,首先我們為Label1添加約束,如下所示。我們為Label1添加了Top、Left、Width和Height四個約束,這四個約束足以來確定該Label的位置了。不過需要注意的一點該Label的Width是小於等於某一個值得,此處我們指定的Width <= 200。也就是該Label的Width的最大值為200。約束添加后如下所示:
接下來我們來為並列第二個Label添加約束。因為要求前面Label內容顯示完成后,剩下的部分就顯示右邊Label的內容,所以我們為Label2添加了Left、Top、Right以及Height的約束。當然Left是以右邊的Label為基准的,而Right則是以父視圖為基准的。
從下方截圖中我們可以看出,有些約束添加完是紅色的,這就是約束有沖突了。也就是當前添加的約束不能確實當前控件的位置。從上述的約束我們不難發現,橫向來看,兩個Label的寬度都是不確定的,所以會報錯。
我們可以點擊下方這個紅色的報錯箭頭查看相應的報錯信息。點擊該紅色箭頭會顯示下方這個界面,該界面中會提示相應的錯誤信息。從下面的對話框中我們可以看到具體的錯誤信息是“Content Priority Ambiguity”,也就是說“內容優先級是模棱兩可的”。點擊這個紅色的圓圈,會給出相應的解決方案:
- Decrease horizontal hugging of "Second Label" from 251 to 250 to make it grow before other views。
意思大體就是說:需要減小Second Label的水平擁抱優先級,從現在的251換成250。換句話說,也就是將“Second Label”的Content Hugging Priority從251換成250后,下方的問題就會被解決了。“to make it grow before other views”,這句話的意思是降低這個優先級目的是為了讓該視圖在其他視圖之前生長。
翻譯的有些晦澀,我們來用大白話說一下。造成下方錯誤的原因是水平放置的兩個Label的寬度都不確定,而且其內容環抱的優先級又是一致的,所以在運行是我們無法確定是先確定第一個Label的寬度還是先確定第二個Label的寬度,解決方案是將右邊的Label的Content Hugging Priority的優先級調低,當然第一個Label的Content Hugging Priority相對就高了。所以左邊的Label會優先的環繞其內容,也就是說該Label會優先的確定其寬度。當左邊Label的寬度確定了,那么右邊Label的寬度也就是隨着確定了,所以下方的錯誤也就解決了。
下方就是我們將右邊的Label的Content Hugging Priority改成250后的結果。可以看出之前的報錯被解決了。當然,也可以將左邊的Label的Content Hugging Priority的優先級修改成比右邊的高即可。此處我們僅討論了Content Hugging的水平方向上的優先級,豎直方向上的優先級是一樣的,在此就不做過多贅述了。
上面約束添加完以及優先級添加完畢后,我們就可以看一下運行效果了。為了動態的看一下約束的效果,我們為每個Label添加了一個Step控件,從下方運行效果我們不難看出,該控件主要是用來控制對應Label的大小的。下方的運行效果是符合我們之前的預期的。左邊的Label的長度是有一個最大值得,當左邊的Label顯示完成后,右邊剩下的空間就顯示第二個Label的內容了。
三、Content Compression Resistance Priority (內容壓縮阻力優先級)
聊完“內容擁抱優先級”后,接下來我們就來看一下Content Compression Resistance Priority 。內容壓縮阻力優先級,從字面意思上看,該優先級越大則說明內容壓縮阻力越大,也就是說內容越難被壓縮。當兩個Label並排顯示,並且屏幕不足以顯示兩個Label的所有內容時,則會優先壓縮“內容壓縮阻力優先級”越小則先被壓縮。
我們依然采用上一部分的方式,從錯誤入手,在錯誤解決的過程中來認識一下這個“Content Compression Resistance Priority”。首先我們也是讓兩個Label並排顯示,左邊的Label我們暫且稱之為FirstLabel,右邊的Label我們則稱之為SecondLabel。我們為FirstLabel添加的約束有Top、Left、Height以及Width >= 50,我們為SecondLabel添加的約束為Left(以First的Right為參照)、Top、Right、Height以及Width>=102。下方截圖就是我們添加上述約束后的效果:
添加完上述約束后,我們在Storyboard中可以看出是會報錯的。報錯原因也很明確“Content Priority Ambiguity”,也是內容優先級沖突。用大白話解釋就是水平方向上無法確定兩個Label的寬度。當然點擊紅色小圓點也會給出相應的錯誤解決方案:
- Decrease horizontal compression resistance of "Bottom Label2" from 750 to 749 to make it get clipped before other views。
其大體意思就是減少第二個Label的水平壓縮阻力,將現在的750修改成749,使得SecondLabel在其他視圖之前被裁剪。此刻如果你點擊該提示中的“Change Priority”按鍵的話,該錯誤將會被修復。
為了直觀的看一下該優先級的效果,我們添加了一個Switch開關來修改上述兩個Label的優先級。當Switch開關打開時,FirstLabel的壓縮阻力優先級大於SecondLabel,開關關閉就相反了。具體代碼如下所示:
修改完相應的錯誤,以及添加完相應的代碼后,接下來我們來看一下運行結果。當開關打開時,前邊的抗壓縮阻力要大於后邊的Label。而開關關閉時后邊的抗阻力優先級要大於前邊的,運行效果如下所示。
通過上述示例的演示,應該對Content Hugging Priority以及Content Compression Resistance Priority有了直觀的感受,本篇博客就先到這兒吧。下方是上述示例在Github上的分享鏈接,如下所示:
github分享鏈接:https://github.com/lizelu/AutoLayoutContentHuggingAndCompressionResistance