[心得] 纯程式码 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