
按照計(jì)劃,這篇文章將是這個(gè)系列里的最后一篇了。
在上一篇文章中,為了讓最后的三個(gè)第三方登錄按鈕的間距能夠根據(jù)屏幕的寬度自動(dòng)調(diào)整,我先添加了一個(gè)組,再在組里面添加約束,弄的很復(fù)雜,而且這種方法也有一定的局限性。

我在上篇文章了就講過,這個(gè)問題有更簡(jiǎn)單的解決方案。這個(gè)東西叫做StackView,在我之前講過的添加約束的方式中,第一個(gè)按鈕就是。

它可以讓你不用添加約束就能使用Autolayout里的很多功能,以后維護(hù)起來也會(huì)更方便。和上篇文章講的一樣,先拖出三個(gè)按鈕放好,這次不用給他們先放到一個(gè)組里,只要三個(gè)一起選中后,點(diǎn)擊上面說過的Stack按鈕,就將他們放進(jìn)了一個(gè)StackView里了,你可以理解為對(duì)它們進(jìn)行了編組。

編組后發(fā)現(xiàn)三個(gè)按鈕變成垂直排列的同學(xué)先不要急,后面我會(huì)講到如何把它們變成水平分布的。這樣我們就將它們都放到了一個(gè)組里了,接下來先給這個(gè)組添加約束,和之前用的方法一樣。組的寬度還是設(shè)置為屏幕寬度的0.6倍。添加完成后變成這樣了。

但是里面的按鈕并沒有和我們想象的一樣平均分布,在上篇文章中,我們添加了很多約束,將這些按鈕固定在了組里的某些特定的位置。你也可以在StackView里面添加約束,但是這里我們完全沒必要這么做。我們只要選中整個(gè)StackView,就能在右邊欄看到它的屬性了。只要修改一個(gè)選項(xiàng)就能達(dá)到我們要求的效果。

下面我就解釋一下這些選項(xiàng)代表的是什么意思。
第一個(gè): Aixs 定義的是這個(gè)組的分布方向,我們?nèi)齻€(gè)按鈕是水平分布的,所以這里不需要修改,如果你編組后他們是垂直分布的,只需要在這里將它們改成Horizontal就行了。
第二個(gè) :Alignment 定義的是組內(nèi)元素的對(duì)齊方式,你可以在這里設(shè)置上對(duì)齊,下對(duì)齊之類的,因?yàn)檫@三個(gè)按鈕大小是一樣的,所以對(duì)齊方式也無所謂了,使用默認(rèn)的就行。
第三個(gè):Distribution 定義的是他們的分布方式,我們只要在這里選擇equal spaceing 就能讓他們平均分布了。
第四個(gè) : Spaceing 是用來定義相鄰元素之間的距離的,你可以在后面的輸入框中輸入你想要的數(shù)值。
修改好了Distribution后,我們的工作就完成了。

StackView的威力不限于此,假設(shè)現(xiàn)在產(chǎn)品經(jīng)理屁顛屁顛地跑來和你說,我們又多了一個(gè)第三方登錄的渠道,需要加上去。如果你使用的是我在上篇文章中的做法,那么現(xiàn)在你必須從頭來過,而且那種將三個(gè)按鈕放在最左,中間,最右的做法也完全失效了,必須得想出新的辦法來。
而如果你使用的是StackView,那這個(gè)問題完全不叫什么問題,你只要從控件庫里面拖出一個(gè)新的按鈕,直接扔到這個(gè)StackView里面就行了,其他的東西都是自動(dòng)幫你搞定的。

再講一個(gè)StackView的實(shí)際應(yīng)用,假設(shè)我們?cè)O(shè)計(jì)了這樣一個(gè)頁面,想象一下,如果你一個(gè)個(gè)的去添加約束的話,會(huì)是一件多么麻煩的事情,而當(dāng)需要在中間在插進(jìn)一行新的內(nèi)容的時(shí)候,那會(huì)讓你更加痛苦。

而如果你使用的是StackView的話,這一切都變的非常簡(jiǎn)單。首先你將左邊的一整列都放進(jìn)一個(gè)StackView里面,這時(shí)候的Aixs應(yīng)該是Vertical,在Alignment里將對(duì)齊方式改為Trailing(尾對(duì)齊),然后Spaceing里面調(diào)整一下行間距就可以了。
用同樣的方式將右邊的文字也都放進(jìn)一個(gè)StackView里面,Alignment里設(shè)置Leading(首對(duì)齊),將Spaceing里的數(shù)字調(diào)整到和左邊的一樣。
最后將左右兩個(gè)StackView再放進(jìn)一個(gè)StackView里面,根據(jù)需要在Spaceing 里面調(diào)整它們之間的距離。將這個(gè)總的StackView放到你想要的位置就完成了。要添加新的一行,只需要將它們拖進(jìn)之前設(shè)置好的StackView里就可以了。
StackView背后使用的也是AutoLayout,所以你還可以在StackView里面添加約束,做出更復(fù)雜的頁面布局。
事實(shí)上蘋果建議你將StackView作為一個(gè)最基礎(chǔ)的元素來構(gòu)建你的整個(gè)頁面,因?yàn)樗鼘?shí)在是太方便了。
約束的優(yōu)先級(jí) Constraint Priorities
我在之前講過,只有當(dāng)能從你給的約束關(guān)系中推斷出位置和大小信息,而且還沒有沖突時(shí),才能通過。
在現(xiàn)實(shí)開發(fā)中,有可能會(huì)出現(xiàn)約束之間沖突的情況,這時(shí)候我們?cè)撊绾翁幚砟兀繉?shí)際上不是所有的約束都是必須滿足的。還記得我在上篇文章中講過的雙擊修改約束嗎?雙擊約束線后會(huì)彈出這樣一個(gè)Popup,其中第二行的Priority 就是這個(gè)約束的優(yōu)先級(jí)。

你可以給約束設(shè)定一個(gè)優(yōu)先級(jí),從0到1000,默認(rèn)約束的優(yōu)先級(jí)為1000,也就是說是必須滿足的。但如果你將優(yōu)先級(jí)調(diào)整到0到999之間,那就意味著這個(gè)約束并不是必須滿足的,而是根據(jù)實(shí)際情況來取舍。當(dāng)出現(xiàn)沖突時(shí),AutoLayout會(huì)根據(jù)Priority數(shù)值的大小來選擇優(yōu)先滿足哪些約束,數(shù)值越高,就越優(yōu)先滿足。
可是我們不該在一開始就避免去設(shè)置有沖突的約束么?如果我們一開始就去避免這個(gè)問題,那優(yōu)先級(jí)還有什么用?
下面我講一個(gè)例子來演示一下約束優(yōu)先級(jí)的實(shí)際應(yīng)用。
假設(shè)我們?cè)谧鲆粋€(gè)軟件,在這個(gè)軟件里我們給出了兩種基本的操作:打賞 和 支持。
規(guī)則是這樣的:打賞就是你給這個(gè)作者一定的虛擬幣,每個(gè)用戶可以進(jìn)行無限次數(shù)的打賞。
支持,則更多的是精神上的自持,每個(gè)用戶對(duì)于某個(gè)特定的觀點(diǎn)只能支持一次。
通過以上的描述我們可以設(shè)計(jì)這樣兩個(gè)按鈕:

因?yàn)橹С职粹o只有一次點(diǎn)擊機(jī)會(huì),所以當(dāng)支持按鈕點(diǎn)擊過后它就變成不可點(diǎn)擊狀態(tài),它的使命也就完成了。

但是,既然“支持”這個(gè)按鈕點(diǎn)過以后就失效了,為什么不將它拿掉不顯示呢??墒侨绻サ糁С职粹o,那么和支持按鈕相關(guān)的約束都沒有了,打賞按鈕的寬度是沒有被定義的。該如何來解決這個(gè)問題呢?
答案就是再創(chuàng)建一個(gè)約束,將打賞的尾部和屏幕最右邊的距離設(shè)置為10 。這樣打賞按鈕的尾部有了兩個(gè)約束了,一個(gè)說我要和支持按鈕保持10的距離,一個(gè)說我要和屏幕的右邊保持10的距離,顯然這兩個(gè)約束是沖突的。解決這個(gè)沖突的辦法就是將新加的約束的優(yōu)先級(jí)降低。在下圖我用虛線表示。

這樣初始狀態(tài)時(shí),因?yàn)榈诙€(gè)約束并不是必須滿足的,所以一開始是被舍棄的。但是當(dāng)支持按鈕被移除后,這個(gè)新加的按鈕正好能派上用處。這樣頁面就變成了這樣:

約束不一定是固定值
前面我講的約束都是一個(gè)固定的數(shù)值,但實(shí)際上著并不是必須要這樣的。你可以設(shè)置他們之間的關(guān)系,大于等于某個(gè)值,等于某個(gè)值,小于等于某個(gè)值。再看一下修改約束的Popup,第一個(gè)選項(xiàng)就是讓你選擇這個(gè)關(guān)系,只不過默認(rèn)的是等于。

下面再看一個(gè)實(shí)際情況。

假如我有這樣一行內(nèi)容,前面是描述,后面是內(nèi)容,我們規(guī)定了它們各自離開屏幕兩個(gè)邊的距離。但是我們并不是十分關(guān)心它們之間的距離,所以我們可以不設(shè)置它們之間的約束,讓他們根據(jù)顯示的內(nèi)容自動(dòng)調(diào)整好了。然而,當(dāng)后面這個(gè)交易編號(hào)變的特別長(zhǎng)的時(shí)候,就會(huì)出現(xiàn)文字疊加的情況。所以為了保證它們不重疊,我們還是需要在他們之間設(shè)置一個(gè)約束,如規(guī)定它們的距離必須大于等于10。這樣大多數(shù)情況下能保證這兩個(gè)label還是能自由伸縮,而且不會(huì)出現(xiàn)重疊的情況。當(dāng)編號(hào)變的特別長(zhǎng)時(shí)可以觸發(fā)新的適配機(jī)制,如讓編號(hào)的字體縮小,而不是直接重疊到前面的標(biāo)題上去。

Auotresizing
不得不承認(rèn)的是,有時(shí)候設(shè)置約束是一件很麻煩的事情,特別是你面對(duì)的是復(fù)雜的界面的時(shí)候,而有時(shí)候,你還沒想好要設(shè)置成怎么樣,只是想先試試。這時(shí)候你就可以試試蘋果推出的新功能,前提是你要把你的Xcode 升級(jí)到8.0以上。
這個(gè)功能就是Auotresizing,它讓你不設(shè)置約束就能快速驗(yàn)證你的想法。它使用起來也非常簡(jiǎn)單,在選中你要設(shè)置的視圖的前提下,當(dāng)你選擇左邊欄中的標(biāo)尺icon 后就能看到Auotresizing功能了。

能看到中間的正方形四周有四個(gè)約束,虛線狀態(tài)下表示這個(gè)約束沒有添加,當(dāng)你點(diǎn)一下后,它就會(huì)變成實(shí)線,表示已經(jīng)添加上了,而中間的兩個(gè)帶有箭頭的虛線則代表是否允許伸縮。默認(rèn)是不允許的,如果你點(diǎn)擊寬度方向的以后,這條線就變成了實(shí)線,表示寬度方向是可以自由伸縮的。邊上還會(huì)有一個(gè)小動(dòng)畫來告訴你這些視圖會(huì)怎么變。有興趣的可以去嘗試一下。
到這里,這個(gè)系列的文章就算結(jié)束了。當(dāng)然我這個(gè)系列的文章里不可能提到所有和AutoLayout的知識(shí)。很多人看完以后可能也就忘了如何去添加約束,但是我覺我寫這個(gè)系列的文章,最大的目的不是讓你看完以后能像程序員一樣去開發(fā)自己設(shè)計(jì)的頁面了,而是讓你了解這種相對(duì)布局的思想。希望看完這一系列文章后,當(dāng)你再次看設(shè)計(jì)稿時(shí),能有一種新的視角。
Via: DDC
