# iOS - AutoLayout -1

iOS - AutoLayout -1

1、AutoLayout

自動(dòng)布局(AutoLayout)是iOS6引入的關(guān)系布局,實(shí)現(xiàn)動(dòng)態(tài)位置和多視圖關(guān)系的布局方式,是對(duì)frame布局和AutoresizingMask的不足進(jìn)行補(bǔ)充的一種方式,現(xiàn)在已經(jīng)成為主流的布局方案,由于原始創(chuàng)建方式比較復(fù)雜,可以使用優(yōu)秀的第三方框架方便創(chuàng)建約束(Swift: SnapKit, Objective-C: Masonary)。
AutoLayout,是一個(gè)基于約束,動(dòng)態(tài)計(jì)算視圖大小和位置的庫(kù),以布局引擎系統(tǒng)Layout Engine為核心,采用了 Cassowary布局算法,Layout Engine統(tǒng)一管理了布局的創(chuàng)建、更新、銷(xiāo)毀,將視圖的約束、優(yōu)先級(jí)、固定大小通過(guò)計(jì)算轉(zhuǎn)換成最終的大小和位置。
在Layout Engine中,每當(dāng)約束發(fā)生變化,會(huì)重新計(jì)算布局,獲取到布局后調(diào)用superview.setNeedLayout(),然后觸發(fā)Deffered Layout Pass做容錯(cuò)處理,然后Layout Engine會(huì)從上到下調(diào)用layoutSubviews()來(lái)確定各子視圖的位置(通過(guò)Cassowary算法計(jì)算),算出來(lái)后將子視圖的frame從Layout Engine里拷貝出來(lái),然后進(jìn)行繪制、渲染,得到我們眼中看到的UI效果。

cassowary算法

1997年,一個(gè)名叫 Cassowary 的布局算法解決了用戶(hù)界面的布局問(wèn)題,它通過(guò)將布局問(wèn)題抽象成線(xiàn)性等式和不等式約束來(lái)進(jìn)行求解。
Cassowary能夠有效解析線(xiàn)性等式系統(tǒng)和線(xiàn)性不等式系統(tǒng),用來(lái)表示用戶(hù)界面中那些相等關(guān)系和不等關(guān)系?;诖?,Cassowary開(kāi)發(fā)了一種規(guī)則系統(tǒng),通過(guò)約束來(lái)描述視圖間的關(guān)系。約束就是規(guī)則,這個(gè)規(guī)則能夠表示出一個(gè)視圖相對(duì)于另外一個(gè)視圖的位置。

由于Cassowary算法讓視圖位置可以按照一種簡(jiǎn)單的布局思路來(lái)寫(xiě),這些簡(jiǎn)單的相對(duì)位置描述可以在運(yùn)行時(shí)動(dòng)態(tài)的計(jì)算出視圖具體的位置。視圖位置寫(xiě)法簡(jiǎn)化,界面相關(guān)代碼也就更易于維護(hù)。蘋(píng)果公司也是看中了這一點(diǎn),將其引入了自己的系統(tǒng)中。

AutoLayout的性能

Auto Layout 進(jìn)行布局時(shí),可以指定一系列的約束,比如視圖的高度、寬度等等。而每一個(gè)約束其實(shí)都是一個(gè)簡(jiǎn)單的線(xiàn)性等式或不等式,整個(gè)界面上的所有約束在一起就明確地(沒(méi)有沖突)定義了整個(gè)系統(tǒng)的布局。

在涉及沖突發(fā)生時(shí),AutoLayout 盡量滿(mǎn)足最多并且優(yōu)先級(jí)最高的約束, break一些優(yōu)先級(jí)低的約束

在iOS12之前,AutoLayout在處理多層級(jí)嵌套時(shí),開(kāi)銷(xiāo)呈指數(shù)級(jí)躍增,但是從iOS12開(kāi)始,蘋(píng)果補(bǔ)齊了這一漏洞,所以在iOS12及以后,我們就開(kāi)始放心的使用AutoLayout,更多關(guān)于AutoLayout的性能問(wèn)題及解決方法,請(qǐng)查看WWDC2018-202

AutoLayout布局原理和語(yǔ)法

AutoLayout是通過(guò)約束來(lái)實(shí)現(xiàn)布局的。一個(gè)view一旦使用了AutoLayout約束,那么它的frame將永遠(yuǎn)都是0

在使用AutoLayout之前需要兩個(gè)準(zhǔn)備工作

  • 設(shè)置translatesAutoresizingMaskIntoConstraints為false
  • 如果是viewControl則AutoLayout適配寫(xiě)在
  • (void)updateViewConstraints中。
    如果是view則AutoLayout適配寫(xiě)在
  • (void)updateConstraints中。實(shí)際上,這也正是AutoLayout好處之一,可以集中將一個(gè)controller和view的適配在一個(gè)方法中。

參數(shù)

 let constraint = [NSLayoutConstraint (item: <#T##Any#>, attribute: <#T##NSLayoutConstraint.Attribute#>, relatedBy: <#T##NSLayoutConstraint.Relation#>, toItem: <#T##Any?#>, attribute: <#T##NSLayoutConstraint.Attribute#>, multiplier: <#T##CGFloat#>, constant: <#T##CGFloat#>)]

創(chuàng)建一個(gè)AutoLayout需要七個(gè)參數(shù),他們分別是

(1)Item:被約束對(duì)象
(2)第一個(gè)attribute:被約束對(duì)象的關(guān)系
(3)relatedBy:約束描述
(4)toItem:約束源
(5)第二個(gè)attribute:約束源的關(guān)系
(6)multiplier:約束系數(shù)
(7)constant:約束常數(shù)

  • 其中 attributebute 對(duì)應(yīng)的屬性如下
public enum Attribute : Int {        
        case left = 1
        case right = 2
        case top = 3
        case bottom = 4
        case leading = 5
        case trailing = 6
        case width = 7
        case height = 8
        case centerX = 9
        case centerY = 10
        case lastBaseline = 11
        @available(iOS 8.0, *)
        case firstBaseline = 12
        @available(iOS 8.0, *)
        case leftMargin = 13
        @available(iOS 8.0, *)
        case rightMargin = 14
        @available(iOS 8.0, *)
        case topMargin = 15
        @available(iOS 8.0, *)
        case bottomMargin = 16
        @available(iOS 8.0, *)
        case leadingMargin = 17
        @available(iOS 8.0, *)
        case trailingMargin = 18
        @available(iOS 8.0, *)
        case centerXWithinMargins = 19
        @available(iOS 8.0, *)
        case centerYWithinMargins = 20
        case notAnAttribute = 0
    }

其中l(wèi)eading 、trailing 是表示前、后,
left、right 表示左右,某種意義上leading == left,trailing == right,但是當(dāng)旋轉(zhuǎn)的時(shí)候會(huì)出現(xiàn)一些問(wèn)題,所有建議大家使用 leading 、trailing

  • relatedBy 對(duì)應(yīng)的屬性如下
public enum Relation : Int {
        case lessThanOrEqual = -1
        case equal = 0
        case greaterThanOrEqual = 1
    }

約束描述主要就是<= 、==、 >= 主要是用于不確定大小和坐標(biāo)的約束

  • 約束系數(shù)multiplier和約束常數(shù)constant主要是計(jì)算約束關(guān)系最終結(jié)果的,遵循公式"view1.attr1 = view2.attr2 * multiplier + constant"

想準(zhǔn)確的將一個(gè)View動(dòng)態(tài)布局,有時(shí)候往往需要設(shè)置好幾個(gè)約束來(lái)定位view的位置,所以這種代碼寫(xiě)起來(lái)往往比設(shè)置frame更加的冗長(zhǎng),所以就有了AutoLayout的出現(xiàn)。

未完待續(xù)。。。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容