前言:SDAutoLayout 在發(fā)布之后受到了眾多iOS開發(fā)者的青睞和支持,不到半年時間內在GitHub上已經(jīng)獲得2000+star,同時被眾多公司和個人開發(fā)者作為開發(fā)首選自動布局庫。現(xiàn)在,以SDAutoLayout為例簡單介紹一下如何設計一個自動布局庫。
????? 所謂自動布局,其實就是將手動布局的計算過程抽象出一套算法,然后利用約束模型收集view的寬高左右等各個維度對應的數(shù)據(jù),最后在恰當?shù)臅r機根據(jù)約束計算出view的frame。
????? 了解了這個基本原理之后,我們就可以動手設計一個自動布局庫了。在設計自動布局庫的過程中,我們主要需要解決以下幾個問題:
????? 1.何時進行自動布局相關運算?
????? 2.如何實現(xiàn)自動布局算法?
????? 3.如何設計約束模型管理機制?
???? 4.如何設計一套簡潔的連式語法API?(此步非必須項,僅供有興趣者參考,以SDAutoLayout為例)
????? 5.如何實現(xiàn)自動計算cell高度?
1.何時進行自動布局相關運算?
? ? ? 首先,什么時候進行自動布局相關運算才最合適呢?我們知道,當一個view的frame發(fā)生改變或者由于其他情況需要調整子view就會觸發(fā)layoutSubvies方法,在手動布局時我們經(jīng)常通過重寫這個方法來實現(xiàn)對子view的調整。但是我們要設計自動布局庫時,顯然不應該強行重寫view的layoutSubvies方法,這樣就會破壞了開發(fā)者對view的自主監(jiān)聽和掌控,因此,layoutSubvies方法執(zhí)行完畢之后才是我們進行自動布局相關運算的最佳時機。好的,那么究竟如何監(jiān)控這個“最佳時機”的到來呢?此時我想熟悉OC運行時的同學已經(jīng)想到了,沒錯,就是利用OC的黑魔法“Method Swizzling”即可完美解決,代碼如下(源碼地址?):
2.如何實現(xiàn)自動布局算法?
????? 當解決了自動布局運算時機的問題之后,我們面臨的下一個問題就是如何設計自動布局算法,這也是整個自動布局庫最核心的部分。
????? 在講這個布局算法之前,有必要先說一下我總結出的一個自動布局算法要素:先計算絕對屬性,后計算相對屬性。
????? 那么,何為“相對屬性”?相對屬性就是需要參照于其他物體才有意義的屬性。比如我們會說“河南在河北的南面”,那么這個“南”就是一個相對屬性,有了河北作為參照,這個“南”才是有意義的,如果你只說“河南在南面”,那么這個“南”就是沒有意義的。在自動布局中,一個view的x、y、centerX、centerY、left、right等屬性就屬于這種相對屬性。
????? 對比“相對屬性”,“絕對屬性”就很好理解了,所謂“絕對屬性”就是不依賴于參照物改變而改變的屬性。比如我會說“iPhone6 是4.7英寸屏幕”,那么這個“4.7英寸”就是絕對屬性,他不會因為和其他參照物比較而改變。在自動布局中,一個view的width、height屬性就是這種絕對屬性。
? ? ? 另外,在針對每個“相對屬性”計算過程中,“寬高校驗”是非常有必要的,如果寬高是不準確的,那么計算出來的right、bottom、centerX、centerY等屬性值也肯定是不準確的。示例代碼如下(源碼地址):
3.如何設計約束模型管理機制?
? ? ? 然后,我們還要設計一下自動布局約束管理機制,也就是說,每個view的約束該交由誰來管理呢?是view自己?還是view的superView呢?結合剛剛對問題一的分析,既然是父view在調用layoutSubvies方法之后再進行自動布局計算,那么讓父view來管理所有子view的約束就再合理不過了。在SDAutoLayout中,每個view都有一個autoLayoutModelsArray數(shù)組來管理子view的約束,子view在調用sd_layout方法時候會初始化一個約束模型并添加到其父view的autoLayoutModelsArray數(shù)組中,這就是為什么在使用SDAutoLayout過程中要先將子view添加到父view然后再做布局設置的原因了。示例代碼如下(源碼地址):
4.如何設計一套簡潔的連式語法API?
? ? ? 鏈式語法以其簡潔明了的優(yōu)點受到了眾多開發(fā)者的推崇,在SDAutoLayout庫中,約束模型將各種布局數(shù)據(jù)設置的操作封裝進一個個block中,每次置一個維度的約束時實際上是調用了這個維度對應的block,把相關參數(shù)以(參數(shù)1,參數(shù)2)的形式傳遞給block進行相關設置,然后block每次把約束模型自身作為返回結果傳遞下去,這樣就可以再次用"."來調用其他維度約束對應的block。示例代碼如下(源碼地址):
5.如何實現(xiàn)自動計算cell高度?
? ? ? SDAutoLayout為開發(fā)者提供了簡潔高效的cell高度自動計算方法,使用者只需調用一行代碼“[yourCell setupAutoHeightWithBottomView:bottomView bottomMargin:bottomMargin];”即可輕松實現(xiàn)cell高度自動計。
? ? ? 為了實現(xiàn)此功能,SDAutoLayout庫在內部建立一個和你的cell一樣的模型,然后把你傳遞過來的model數(shù)據(jù)賦值給模型cell,設置完成后調用“[self.modelCell.contentView layoutSubviews]”方法來計算cell的真實高度然后返回給你的tableView,同時還會建立cell高度緩存庫以供tableView滾動時直接返回cell高度而不必再次計算,如果有需要,你也可以開啟cell的Frame緩存機制,這樣就會在你的cell出現(xiàn)的時候直接給cell內部控件設置frame而不必時時計算調整,從而大大增加了滾動流暢度。示例代碼如下(源碼地址):
? ? ? 好了,今天先簡單介紹到這里,后期還會針對以上提到的五點內容進行詳細深入的介紹,如有好的意見和建議歡迎到SDAutoLayout的GitHub地址https://github.com/gsdios/SDAutoLayout issue我,Thanks!
SDAutoLayout的GitHub地址:https://github.com/gsdios/SDAutoLayout
SDAutoLayout使用者開發(fā)的部分app截圖http://www.lxweimin.com/p/9bc04d3effb8
自動布局QQ交流群:497140713(1群)? 519489682(已滿)
自動布局視頻教程:
SDAutoLayout 基礎版視頻教程:http://www.letv.com/ptv/vplay/24038772.html
SDAutoLayout 進階版視頻教程:http://www.letv.com/ptv/vplay/24381390.html
SDAutoLayout 原理簡介視頻教程:http://www.iqiyi.com/w_19rt0tec4p.html