作者denkeni (Denken)
看板MacDev
标题[心得] 纯程式码 Auto Layout 与概要笔记
时间Mon Mar 27 22:38:35 2017
# 前言
这几年来工作上写 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 架构下做动态效果的基础
--
我最近写了一个叫作「工作咖啡馆」的 iOS App
https://goo.gl/iBWJSs
我朋友拖拖拉拉也生出了 Android 版叫作「CaffeeTrip」
https://goo.gl/HnUQWQ
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.170.206.103
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/MacDev/M.1490625520.A.A68.html
※ 编辑: denkeni (1.170.206.103), 03/27/2017 23:04:23
1F:推 Neisseria: Cafe Nomad 网站蛮有意思的 (离题离很大) 03/27 23:11
2F:推 cryinglove: 推 03/27 23:19
※ 编辑: denkeni (1.170.206.103), 03/28/2017 00:13:17
3F:→ shinrenpan: UIStackView 要看公司给不给用吧 XD 03/28 07:57
我现在公司的专案有用这个,向前相容到 iOS 7
https://github.com/oarrabi/OAStackView
4F:推 jeff12280: 推 03/28 10:32
5F:→ uranusjr: Cafe Nomad 手机很难用我觉得, 但可能可以考虑合作... 03/28 14:02
正是我签名档写的东西?都是接 Cafe Nomad API 写的 app
※ 编辑: denkeni (219.85.130.230), 03/29/2017 01:22:48
6F:推 areyo: 真是好文 03/29 08:20
7F:推 Blueshiva: 其实单一个NSLayoutConstraint并不足以定义一个View的 03/29 11:28
8F:→ Blueshiva: 资讯,一个View还是要有原点及宽高,或者四个边界的限 03/29 11:29
9F:→ Blueshiva: 制。Constraint我个人比较把它当成是限制一个View性质 03/29 11:30
10F:→ Blueshiva: 的规则,规则太松散则定义不出唯一的结果,太多也有可 03/29 11:31
11F:→ Blueshiva: 能因为互相矛盾变成无解 03/29 11:31
行文仓促,可能我用词不慎导致阅读起来有此误会
我想说明的是只需要 constraint 这一个 API,而不是只用一个 constraint
稍微修改了用词,也感谢您的补充
而我原文网页版中,前两个范例原始码,刚好对应了您说的那两种限制条件写法:
1. centerX, centerY, width, height
2. top, bottom, left, right
※ 编辑: denkeni (219.85.130.230), 03/29/2017 11:51:48
加入 延伸学习支线
※ 编辑: denkeni (1.171.40.186), 03/29/2017 18:28:08
※ 编辑: denkeni (61.64.210.250), 03/30/2017 03:46:37