[心得] 純程式碼 Auto Layout 與概要筆記(一)

作者: denkeni (Denken)   2017-03-27 22:38:35
# 前言
這幾年來工作上寫 iOS app,都是用純程式碼與原生的 Auto Layout。
一路上發現網路上純程式碼的寫法教學還是不多,
Visual Format Language 更是少,
於是將這幾年碰壁學出來的心得,以我理解的方式,整理成這份概要教學。
有所疏漏誤解,還請先進不吝指教改正。
(由於批踢踢不方便貼程式碼
含完整程式碼與後續文章更新,請到網頁版 https://goo.gl/BV7KgN )
預計會有三篇:
* 從 setFrame 到 Auto Layout constraint
* Visual Format Language (VFL)
* 何時需要 UIStackView?
本篇下述範例,都整理成 Swift Playground 在這專案裡
https://github.com/denkeni/Auto-Layout-Programmatically
# 從 setFrame 到 Auto Layout constraint
要排版出一個長方形的 UIView,最早的方式是設定 frame:
https://cdn-images-1.medium.com/max/800/1*kV52_o1n08x-yGJu3jzsQA.jpeg
```
subview.frame = CGRect(x: 100, y: 50, width: 200, height: 100)
```
前兩個 (x, y) 設定長方形左上角的原點
後兩個 (width, height) 設定長方形的寬與長
這樣就能唯一決定長方形的樣子
一般來說是在繼承 `layoutSubviews()` 中描述這些 subviews 的關係
畫面有變化時(譬如旋轉)就能即時更新
然而這樣的方式,在排版更多 subview 時
就很容易需要相當多的算術
適度配合 autoresizingMask 能緩解這問題
但在不同 subview 排版互相依賴時,依然無法很好地解決
(這裡不討論 autoresizingMask,因為後面的 Auto Layout 就能取代)
iOS 6 之後提供另一套更高層次的機制:Auto Layout
它的根本基礎就只有一個 constraint API:
```
NSLayoutConstraint(item: y, attribute: y.attribute, relatedBy: =,
toItem: x, attribute: x.attribute,
multiplier: m, constant: c
```
只用這個 API 就足以完整描述一個 UIView 的樣子
這個 API 是在描述一個線性等式關係:`y = m x + c`
相較於 setFrame 只有 x, y, width, height 四種描述屬性
Auto Layout 提供了更多的描述屬性(NSLayoutAttribute):
https://cdn-images-1.medium.com/max/800/1*hew9LhCYxl-1vog26eDR3g.png
而描述這些變數之間的關係
是用線性關係 ( y = m x + c )(m: multiplier, c: constant)
(甚至可以用不等式 >=, <= 這裡不討論,因為後面的 VFL 更有機會用到)
直接用實例來解釋這個 API
我們改用 Auto Layout constraint 重做前述例子
假設上層 view 是長這樣:
`let view = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))`
可以發現前述長方形其實是在置中位置
只需分別設定 centerX, centerY 和 width, height 如下:
(略)
由此可以發想
必有其他的描述方式,可以達到一樣的排版效果
只要 x 方向與 y 方向上
各有 2 個有效給定的 Auto Layout Constraint(等式)
就可以唯一決定長方形的樣子
那麼也可以這樣做,分別設定 top, bottom, left, right 如下:
(略)
當然這樣旋轉後的樣子,會與前者不同
所以應該根據 subview 的本質
選擇最合理正確的描述方式
掌握了 Auto Layout constraint 其實就是描述 y = m x + c 的線性關係之後
很快就能明白
不論是用 Storyboard/Interface Builder 或是
NSLayoutAnchor
PureLayout
Masonry… 等等
其實都是奠基於這一個 API 而已
以 iOS 9 之後支援的 NSLayoutAnchor 為例,重做前述例子:
(略)
P.S. 延伸學習支線:從這篇你可以岔出去自學的題材
* Auto Layout constraint 可以設定 priority
* Auto Layout constraint 在 activate 之後,constant 值還可以動態修改!
這也是 Auto Layout 架構下做動態效果的基礎
作者: Neisseria (Neisseria)   2017-03-27 23:11:00
Cafe Nomad 網站蠻有意思的 (離題離很大)
作者: cryinglove (毓™)   2017-03-27 23:19:00
作者: shinrenpan (iOS5)   2017-03-28 07:57:00
UIStackView 要看公司給不給用吧 XD
作者: jeff12280 (猜不透平常心)   2017-03-28 10:32:00
作者: uranusjr (←這人是超級笨蛋)   2017-03-28 14:02:00
Cafe Nomad 手機很難用我覺得, 但可能可以考慮合作...
作者: areyo (沒有名字的怪物)   2017-03-29 08:20:00
真是好文
作者: Blueshiva (龍野南雲)   2017-03-29 11:28:00
其實單一個NSLayoutConstraint並不足以定義一個View的資訊,一個View還是要有原點及寬高,或者四個邊界的限制。Constraint我個人比較把它當成是限制一個View性質的規則,規則太鬆散則定義不出唯一的結果,太多也有可能因為互相矛盾變成無解

Links booklink

Contact Us: admin [ a t ] ucptt.com