Auto layout 的使用

1,220 阅读4分钟

什么是Auto Layout

Auto Layout,是苹果公司提供的一个基于约束布局,动态计算大小和位置的库,并且已经集成到了Xcode开发环境里里。

在引入Auto Layout之前,都是采用手动布局的方式。手动布局的方式原始落后,界面开发维护效率低,为了提高更好得界面引擎给开发这体验,随之引入Auto Layout。

来历

Cassowary是个解析工具包,能够有效解析线性等式系统和线性不等式系统,用户的界面中总是会出现不等关系和相等关系,Cassowary开发了一种规则系统可以通过约束来描述视图间关系。约束就是规则,能够表示出一个视图相对于另一个视图的位置。

Auto Layout生命周期

Auto Layout 用一整套布局引擎管理布局的创建,更新,销毁。这一整套布局引擎系统叫做Layout Engine,是Auto Layout的核心,主导着整个布局页面。

每个视图在得到自己的布局之前,Layout engine会将视图,约束,优先级,固定大小计算通过转换成最终的大小和位置。在Layout engine里,会有约束变化到Deferred Layout Pass 再到应用Runloop 在回到约束变化这样的循环机制。如下图所示:

约束变化

触发约束变化包括:

  • Activating 或 Deactivating
  • 设置constant 或 priority
  • 添加和删除时图

这个Engine遇到约束变化会重新计算layout,获取新值后会call它的superview.setNeedslayout()

Deferred Layuot Pass

在这个时候主要是做些容错处理,更新约束有些没有确定或者缺失布局声明的视图会在这里处理。接着从上而下调用layoutSubviews()来确定视图各个子视图的位置,这个过程实际上就是将subview的frame从layout engine里拷贝出来。这里要注意重写layoutSubviews()或者执行类似layoutIfNeeded这样可能会立刻唤起layoutSubviews()的方法,如果要这样做需要注意手动处理的这个地方自己的子视图布局的树状关系是否合理。

生命周期中需要注意的事项

  • 不要期望frame会立刻变化
  • 在重写layoutSubviews()时需要非常小心

使用API约束

[NSLayoutContraint constraintWithItem:view1 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-5]

使用VFL语言约束

[NSLayoutConstraint constraintWithVisualFormat:@“[view1]-[view2]" options:0 metrics:nil views:viewsDictionary;

VFL几个例子

  • [view1(50)]-10-[view2(100)] 表示view1宽50,view2宽100,间隔10
  • [view1(>=50@750)] 表示view1宽度大于50,约束条件优先级为750(优先级越大优先执行该约束,最大1000)
  • V:[view1][view2(==view1)] 表示按照竖直排,上面是view1下面是一个和它一样大的view2
  • H:|-[view1]-[view2]-[view3(>=20)]-| 表示按照水平排列,|表示父视图,各个视图之间按照默认宽度来排列

VFL的语法

  1. 标准间隔:[button]-[textField]
  2. 宽约束: [button(>=50)]
  3. 与父视图的关系: |-50-[purpleBox]-50-|
  4. 垂直布局: V:[topField]-10-[bottomField]
  5. Flush Views:[maroonView][buleView]
  6. 权重:[button(100@20)]
  7. 等宽:[button(==button2)]
  8. Multiple Predicates: [flexibleButton(>=70,<=100)]

注意事项

  1. H:和V:每次都是使用一个
  2. 视图变量名出现在方括号中,例如[view]
  3. 字符串中顺序是按照从顶到底。从左到右
  4. 视图间隔以数字常量出现,例如-20-
  5. |表示父视图

使用Auto Layout时需要注意的点

  • 注意禁用 Autoresizing Masks。对于每个需要使用Auto Layout的视图需要调用setTranslatesAutoresizingMaskIntoConstraints:NO
  • 布局原理是由外向里布局,最先屏幕尺寸,在一层一层往里布局各个元素的大小
  • 删除视图时直接使用removeConstraint和removeConstraints时需要注意这样删除是没法删除视图不支持的约束导致view中还包含着那个约束(使用第三方库时需要特别注意下)。解决这个的办法就是添加约束时用一个局部变量保存下,删除时进行比较删掉和先前那个,还有个办法就是设置标记,constraint.identifier = @“What you want to call”。
  • VFL语句里不能包含空格和>,<这样的约束

布局约束规则

Auto Layout的Debug

  1. Unsatisfiable Layouts 约束冲突,同一时刻约束无法同时满足
  2. Ambiguous Layouts: 约束缺失
  3. Logical Errors: 布局中的逻辑错误
  4. 视图约束不合法,每个约束至少要引用一个视图,删除视图时一定要注意
  5. 无公共父视图之间的相互添加约束会出问题

推荐使用的Auto Layout 第三方库

  • Masonry
  • Cartography
  • SDAutoLayout