在日常開發(fā)中我們經(jīng)常會(huì)看到啦逆,當(dāng)superview的bounds發(fā)生變化的時(shí)候,他的subview也會(huì)隨之移動(dòng)笛洛,但這是為什么呢夏志?在superview的size發(fā)生變化的時(shí)候,subview內(nèi)部發(fā)生了什么呢苛让?看似簡單的現(xiàn)象中其實(shí)包含了很多知識沟蔑,估計(jì)再接下來很長的時(shí)間里我將仔細(xì)梳理關(guān)于Layout方面的知識,若大家在閱讀過程中發(fā)現(xiàn)什么問題請及時(shí)糾正狱杰,共同進(jìn)步??
說起 layout 其實(shí)我們在開發(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ì)伸縮或拉長等等宣蠕,所以說 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í)例對象备韧,通過數(shù)字來描述一個(gè) view 相對于其他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
對于上面所講到的幾種情況大家可以先畫圖理解一下。在代碼中
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è)屏幕
我們再旋轉(zhuǎn)一下屏幕可以看到
現(xiàn)在是橫屏狀態(tài)但 view 的布局并沒有錯(cuò)亂蔑滓,還是在正確的位置上
現(xiàn)在我們可以看出采用 autoresizing 布局還是蠻簡單的郊酒,也正是因?yàn)樗^簡單只能用來描述 superview 和 subview 之間的位置關(guān)系,無法描述view 與 view 之間的關(guān)系键袱。在有 autolayout 之前燎窘,如果要使用 auto resizing 來實(shí)現(xiàn)比較復(fù)雜的布局還需要介入手動(dòng)布局,調(diào)用
layoutsubviews
方法蹄咖,這種方式一方面比較麻煩褐健,另一方面還容易出錯(cuò)。所以還是讓我們好啊后來研究一下 Autolayout 吧比藻!看看它帶給我們哪些便利!