在日常開發(fā)中我們經(jīng)常會(huì)看到,當(dāng)superview的bounds發(fā)生變化的時(shí)候,他的subview也會(huì)隨之移動(dòng),但這是為什么呢?在superview的size發(fā)生變化的時(shí)候,subview內(nèi)部發(fā)生了什么呢?看似簡(jiǎn)單的現(xiàn)象中其實(shí)包含了很多知識(shí),估計(jì)再接下來很長(zhǎng)的時(shí)間里我將仔細(xì)梳理關(guān)于Layout方面的知識(shí),若大家在閱讀過程中發(fā)現(xiàn)什么問題請(qǐng)及時(shí)糾正,共同進(jìn)步??
說起 layout 其實(shí)我們?cè)陂_發(fā)過程中無時(shí)不刻不在用,特別是在寫界面的時(shí)候,比如適配不同的設(shè)備大小,橫屏豎屏轉(zhuǎn)換的時(shí)候界面不能亂,有些 app 需要適配 iphone 和 ipad 兩種設(shè)配的不同尺寸,還有tableview cell的內(nèi)容自適應(yīng),有些時(shí)候當(dāng)隱藏導(dǎo)航欄和現(xiàn)實(shí)導(dǎo)航欄的時(shí)候界面可能會(huì)伸縮或拉長(zhǎng)等等,所以說 layout 在我們寫界面是很有用的,因此他真的很重要。
Layout 有三種主要的表現(xiàn)形式。分別是:
- Manual Layout(手動(dòng)布局):當(dāng) superview 的大小發(fā)生變化的時(shí)候,會(huì)接受到一個(gè)
layoutSubviews的信息, 之后你通過重寫layoutSubviews方法來手動(dòng)的重新為 subviews 布局,很明顯這將會(huì)導(dǎo)致很大的工作量- Autoresizing(自動(dòng)調(diào)整尺寸):這種方式是 iOS6 之前的一種自動(dòng)布局方式。當(dāng) superview 的大小改變時(shí),subview 會(huì)通過
autoresizingMask屬性來調(diào)整值。這個(gè)會(huì)在后面講到- Autolayout(自動(dòng)布局):它是在 iOS6 引進(jìn)的, 主要通過 view 的
constraint來實(shí)現(xiàn)的。 一個(gè) constraint 其實(shí)就是一個(gè)NSLayoutConstraint實(shí)例對(duì)象,通過數(shù)字來描述一個(gè) view 相對(duì)于其他view 的大小和位置。這比autoresizeingMask更精密更容易理解,一個(gè) view 可以有多個(gè) constraint, 并且他們可以描述任意兩個(gè) view 之間的關(guān)系。其實(shí) auotolayout 在背后幫你實(shí)現(xiàn)了layoutSubviews方法, 你可以不用手寫代碼來實(shí)現(xiàn)很多復(fù)雜的約束。你的 lauout 可以使用以上三種的任何一個(gè)或多個(gè)的組合,但一般來說我們很少會(huì)用手動(dòng)布局,因?yàn)楣ぷ髁看笄倚瘦^低。AutoresizeSubviews 默認(rèn)會(huì)自動(dòng)開啟,除非你設(shè)置 superview 的
autoresizesSubviews屬性為 false,或者你使用了autolayout 則AutoresizeSubviews 將會(huì)被禁用。Autolayout 可以用在任何你想用的地方,是不是很方便呀。需要注意的是,在 Xcode7 及 7以后的版本中,autolayout 會(huì)在xib或者storyboard中默認(rèn)勾選, 如果沒有勾選的話則會(huì)使用autoresizng而不是autolayout喲!
Autoresizing
Autoresizing 主要是通過設(shè)置 subview 的
spring和struts屬性來實(shí)現(xiàn)的。Spring 可以被拉伸,但是 strut 不可以,Spring 和 struts 可以在外部或內(nèi)部,水平或垂直方向指定,因此你可以通過這兩個(gè)屬性來指定一個(gè)view要如何調(diào)整大小護(hù)著調(diào)整位置。
試想一下,一個(gè) view 在他的 super的中心位置,當(dāng)父視圖調(diào)整大小時(shí),view也會(huì)跟著調(diào)整大小。view 將會(huì)在其外部是固定(struts)的在內(nèi)部是彈性(spring)的
繼續(xù)設(shè)想有一個(gè)view在他的 superview 的中心位置,但是 view 不隨父視圖大小的變化而變化,這時(shí)view將會(huì)在外部 spring 內(nèi)部 structs
再設(shè)想有一個(gè)OK按鈕在他父視圖的右下角位置,則 view 在內(nèi)部是 struts,在他右方和下方是外部 struts,在上方和左方則是外部 spring。
最后設(shè)想有一個(gè) textfield 在其 superview 的頂部,并且與 superview 同寬,這時(shí)他的外部是 struts, 但是下邊是 spring, 誰知方向時(shí)內(nèi)部 struts 豎直方向內(nèi)部 spring
對(duì)于上面所講到的幾種情況大家可以先畫圖理解一下。在代碼中
spring和struts是通過的 view 的autoresizingMask屬性來設(shè)置的。autoresizingMask 中的 options 是位掩碼, 這些位掩碼是在定義在一個(gè) struckt 里面,這些位掩碼表明了哪些是需要 spring 的,也就是說,沒有專門設(shè)置 struts 的選項(xiàng),只要沒有設(shè)置,就是 struts 的。默認(rèn)值是.None,也就意味著,所有的方向都是 struts,但是這是不可能的,當(dāng) superview 改變的時(shí)候,subview 肯定會(huì)改變,所以,.None 并不是所有都是 struts ,而是 .FlexibleRightMargin 和 .FlexibleBottomMargin 。
下面我門來舉個(gè)例子,理解一下Autoresizing
let v1 = UIView(frame: CGRectMake(100,111,132,194))
v1.backgroundColor = UIColor.magentaColor()
let v2 = UIView(frame: CGRectMake(0,0,132,10))
v2.backgroundColor = UIColor.greenColor()
let v3 = UIView(frame: CGRectMake(v1.bounds.width-20, v1.bounds.height-20,20,20))
v3.backgroundColor = UIColor.redColor()
self.view.addSubview(v1)
v1.addSubview(v2)
v1.addSubview(v3)
運(yùn)行一下你將會(huì)看到下圖界面:

接下來我們?yōu)?v2 和 v3 分別添加 spring 和 struct 讓他們看起來好像一個(gè) textfild 在界面頂部, 一個(gè) ok 按鈕在界面的右下角
v2.autoresizingMask = .FlexibleWidth
v3.autoresizingMask = [.FlexibleTopMargin, .FlexibleLeftMargin]
v1.bounds.size.width += 40
v1.bounds.size.height -= 50
運(yùn)行結(jié)果如下圖:

上面這個(gè)例子可以看得出來 autoresizing 都做了哪些事情, 不過還是有點(diǎn)人為的改變superview的大小,在日常開發(fā)過程中 superview的大小變化通常都是自動(dòng)的,不受人為控制,比如旋轉(zhuǎn)屏幕到橫屏狀態(tài),接下來我們通過改變v1的frame來達(dá)到想要的效果
v1.frame = self.view.bounds
v1.autoresizingMask = [.FlexibleHeight, .FlexibleWidth];
運(yùn)行一下可以看到,v1充滿了整個(gè)屏幕

我們?cè)傩D(zhuǎn)一下屏幕可以看到

現(xiàn)在是橫屏狀態(tài)但 view 的布局并沒有錯(cuò)亂,還是在正確的位置上
現(xiàn)在我們可以看出采用 autoresizing 布局還是蠻簡(jiǎn)單的,也正是因?yàn)樗^簡(jiǎn)單只能用來描述 superview 和 subview 之間的位置關(guān)系,無法描述view 與 view 之間的關(guān)系。在有 autolayout 之前,如果要使用 auto resizing 來實(shí)現(xiàn)比較復(fù)雜的布局還需要介入手動(dòng)布局,調(diào)用
layoutsubviews方法,這種方式一方面比較麻煩,另一方面還容易出錯(cuò)。所以還是讓我們好啊后來研究一下 Autolayout 吧!看看它帶給我們哪些便利!