核心總結(jié): 自動布局是使用了更貼近自然語言的方式去描述位置的方式, 因此, 其本身具有固定元素以及計算公式, 最后, 得到的數(shù)據(jù)結(jié)果和絕對布局相同, 但是因?yàn)? 自動布局需要一個特殊的根節(jié)點(diǎn)并且形成節(jié)點(diǎn)樹之后才能布局, 因此, 可以讀取數(shù)據(jù)的時機(jī)不同
自動布局的底層實(shí)現(xiàn)原理
自動布局的底層原理
概括: 自動布局就是使用更貼近自然語言的方式描述一個控件的位置信息, 大大降低了計算難度
相對位置最終會被布局引擎換算成絕對位置
思想: 用貼近自然語言的 autolayout 方式描述具體的位置信息, 使用的時候, 根據(jù)每句命令將具體的約束信息轉(zhuǎn)化為 frame 以渲染.
公式&要素 7個
公式: view1.attr1 = view2.attr2 * multiplier + constant
被約束的對象 (item) 以及屬性 (attribute)
約束源的對象 (item) 以及屬性 (attribute)
二者之間的關(guān)系 (=/>/<) 系數(shù) (值得比例) 以及 常數(shù) (constant)
iOS中自動布局的屬性元素: 上下左右前后 寬高 中心點(diǎn) 基線 ( 各種邊距 ), 本質(zhì)上就是 frame 的描述, 但是可以通過設(shè)置上下形成寬高.
原理:
組織: 最頂層的視圖一定是有具體的坐標(biāo)信息, 內(nèi)部的子控件布局時讀取對應(yīng)的約束, 例如 距父視圖上偏移100pt, 就會被轉(zhuǎn)化為 frame.orginal.y = 100; 最終形成GPU可以讀取的坐標(biāo)信息, 并且, 在存在多個控件的情況下, 所有的約束會被分解成 鏈狀+樹狀 進(jìn)行組織, 根視圖就是擁有具體坐標(biāo)信息的最頂層父視圖, 下面的同等級控件以及更下級控件的排列順序, 應(yīng)該是按照添加順序從左至右組織, 形成樹組織
轉(zhuǎn)化: 按照以上原理將所有的布局約束轉(zhuǎn)化 樹狀節(jié)點(diǎn)組織, 讀取的順序類似于 BFS 的讀取方式,先將橫向的同級控件的約束轉(zhuǎn)化為坐標(biāo)點(diǎn)進(jìn)行布局, 之后, 在布局深度的子葉節(jié)點(diǎn).總論: 因?yàn)镚PU在形成光柵化渲染的時候, 一定是要獲取到每個坐標(biāo)點(diǎn)的顏色值, 因此, 無論是設(shè)置控件的 frame 或者是 autolayout, 在渲染之前, 實(shí)際上都會被轉(zhuǎn)化為具體的坐標(biāo)點(diǎn), 因此, autolayout 相對frame來講, 在GPU階段是一樣的, 主要的區(qū)別在于同樣的效果在代碼階段表現(xiàn)是不同的, autolayout 使用了較為貼近自然語言的方式去描述位置信息, 所以在最終階段, 相對 frame就多了一個轉(zhuǎn)化階段, 就是將自然語言描述的位置信息轉(zhuǎn)化為具體的坐標(biāo)信息
Masonry的使用
- 主要函數(shù)
創(chuàng)建: mas_makeConstraints
更新: mas_updateConstraints
重設(shè): mas_remakeConstraints
動態(tài)更新布局:
// 告訴self.view約束需要更新
[self.view setNeedsUpdateConstraints];
// 調(diào)用此方法告訴self.view檢測是否需要更新約束,若需要則更新,下面添加動畫效果才起作用
[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:0.3 animations:^{
[self.view layoutIfNeeded];
}];
部分問題
- 使用了autolayout之后, 控件的frame將會一直為空
- leading(前) 和 training(后) 的實(shí)際使用與 left 和 right 相同, 主要是區(qū)別與 阿拉伯 世界布局習(xí)慣為 從右至左, 也就是, 如果使用 leading 和 training布局, 根據(jù)當(dāng)前使用位置會進(jìn)行對應(yīng)的鏡面翻轉(zhuǎn), 如果使用 left 和 right 進(jìn)行布局, 則切換為 希伯來語 之后, 界面會發(fā)生鏡像轉(zhuǎn)換.