AutoLayout 相關概念介紹和動畫demo前言
最近Apple的動作還是蠻多的,其中有3條很有意思。
- iOS8中設備旋轉,佈局的變化
- 可能的iPhone6屏幕的變化,iPhone和iPad Mac開發越來越趨於統一
- Xcode6中Interface Builder的變化(IB中顯示自定義View)
cocoa touch 開發中適配各種屏幕尺寸已經是能夠預測的了,那麼跟進AutoLayout 也就是必備技能了。
傳統的佈局是如何做的
一開始接觸iOS的時候,我還是蠻喜歡他的佈局系統。簡單來說,一個圖像,我們通過中心點座標,旋轉角度和輪廓大小來定義他在窗口中的位置
這裏的座標和笛卡爾座標系不同的是Y的方向
這裏表示了anchorPoint含義,用於表示position相對bounds的位置,比如(0.5, 0.5)表示中心,(0,0)表示左上角
下面表示了frame bounds position anchorPoint之間的關係,你可能覺得這個anchorPoint似乎沒有什麼用
但是當我們旋轉一個View的時候,好處就來了
傳統佈局的問題
傳統佈局是非常高效的,組合各種變化,可以輕易得實現任意的2D動畫,當然也可以輕易的解決靜態的佈局問題。但是在面對多個屏幕,屏幕旋轉時,或是需要在2個View 中間動態增加一個View的時候顯得非常繁瑣。需要不斷的寫一些計算距離,位置的代碼(甚至還有一些magic number)。網上有很多例子,比如beginning-auto-layout-part-1-of-2,或是大家在平時工作中遇到的3.5inch和4inch屏幕之間的適配。
AutoLayout
AutoLayout使用非常簡單,Xcode的支持也非常直觀。但是因爲和之前的方式有很大的不同,新手一開始很容易遇到一大堆的異常,crash在main函數裏面,讓人非常沮喪。但是在瞭解AutoLayout之後,就會發現這是一個非常非常elegant的佈局解決方案,也很容易理解爲什麼crash,以及應該如何debug。
constraints 約束
AutoLayout 是一個描述各種約束的行爲,比如,一個View 距離父View上邊距多少,相鄰之間的間隔,各個View之間的寬高關係等等。這一系列的條件就是爲了最終確定之前提到的傳統佈局中需要的東西,這個View的大小,位置。所以,當我們設置的條件不足,或是條件衝突時,就會產生異常。
Intrinsic Content Size 固有大小
在使用AutoLayout的時候,UILabel 我們只需要設定他的position,不需要設置寬高,而一個自定義的UIView,我們不僅僅需要位置,還需要設定寬高,這是爲什麼呢?
每一個View 都有一個特別的屬性叫做Intrinsic Content Size,這個可以理解成是一個View的最合適而且最小的寬度和高度。對於UILabe來說,就是至少得把我設定的文字都顯示完整吧,所以系統只需要知道UILabel的位置。而UIView的Intrinsic Content是(0,0)所以需要設置UIView的寬高(或是設定周圍的邊距等等其他關係可以讓系統知道這個View應該多寬,多高)。而Intrinsic Content Size,也是未來自定義View顯示到Xcode中必須設置的屬性之一。
Phases of Display
使用AutoLayout之後,把view顯示到屏幕上面大體分成3步。
- Update constraints
- Layout views
- Display
一般來說layoutSubviews
負責佈局,比如調整View之間的距離,大小,drawRect
負責繪製,比如使用什麼顏色。而AutoLayout則是在layout之前增加了一個設定約束的過程,也就是上面提到了update
constraints
。
在view的layoutSubView
中,如果我們調用了[super
layoutSubView]
系統就把設定的這些約束計算成每個view的bounds,center屬性。當然我們也可以基於AutoLayout的結果,再做佈局的調整。
Display 不是這篇文章的重點,這裏略過
Alignment Rect
仔細閱讀文檔的同學會發現在Apple AutoLayout document中可以看到Alignment Rect 這個傢伙。 AutoLayout中的Left,Right等約束,並不是針對View的frame。而是根據Alignment Rect。在絕大多數情況下Alignment = Frame。但是如果對某些需要交互的元素,而圖片素材很小的時候,就可以利用Alignment把交互區域變大。可以參考UIImage 中的 imageWithAlignmentRectInsets
。
Animation
AutoLayout也可以配合傳統的animation方法,整體代碼結構如下。
1 2 3 4 5 6 7 8 |
|
使用AutoLayout也可以輕易的實現之前的設置frame很難實現的動畫效果。比如下面的例子(很奇怪,優酷吃掉了後面幾秒的動畫…)
使用之前傳統的動畫,實現這個過程,需要計算所有subView之間的距離,位置。而且在修改一個view的frame時,很難做到和其他View的移動速度同步。除非是custom layoutsubview
。做起來相當麻煩。但是用AutoLayout則非常簡潔直觀,只需要設置第一個View的position,然後其他view約定好高度和間隔依次排列就好了。
當然AutoLayout做動畫的時候有的地方也很麻煩,比如希望旋轉view A 的時候,或是使用transform時,很容易產生奇怪的結果。一般來說會設置一個host View通過AutoLayout設定位置,然後在旋轉view A。一句話就是混合起來,各取優點。
其他
- Compression Resistance
- Content Hugging
- 優先級
簡單的來說Compression Resistance 設置view有多大意願(優先級),願意壓縮裏面的內容。Content Hugging設置view 有多大願意(優先級),願意顯示裏面內容之外的部分。
stackoverflow上面有一個很清晰的通過UIButton解釋的[例子],可以很容易理解這2個屬性。