首发于公众号前端
在 iOS 中官方支持的布局方式是 AutoLayout,是一种基于控件之间相互约束关系的自动布局工具。程序员
官方的 AutoLayout 虽然用起来简单,可是有两个很是不方便的地方:swift
第1个问题可使用第三方库来解决,好比 SnapKit(swift)、Masonry(oc)。 性能问题则无解,对于混合布局的 Cell 若是所有使用自动布局就会看到很明显的滑动卡顿。app
对于复杂 Cell 布局,程序员们为了追求极致的帧率,通常都采用手写布局,帧率是上去了而维护的成本也最高。ide
为了兼顾易用性和高效率,Facebook 开发并开源了本身的布局库:Yoga。工具
Yoga 是 FlexBox 的子集,并无所有实现 FlexBox,可是对于大部分应用场景已经足够了。布局
接触过前端开发的朋友对 FlexBox 布局必定不陌生,CSS 写 flex 布局真的太方便了。性能
FlexBox 是不一样于 AutoLayout 的布局方式,FlexBox 是自约束,每一个控件的位置都是相对于自身所在的 Box 相对布局,这就不存在 AutoLayout 基于控件间约束的耦合。flex
Yoga 是基于手动布局的方式,这样效率就很高,并且性能损耗很小,并且使用很简单,用过 Masonry 的同窗能够很快上手。spa
使用方法:
override init(frame: CGRect) {
super.init(frame: frame)
contentView.configureLayout { (layout) in
layout.isEnabled = true
}
override func layoutSubviews() {
super.layoutSubviews()
yoga.applyLayout(preservingOrigin: true)
}
复制代码
layout.isEnabled = true 开启 yoga 布局, 在 layoutSubviews 中使用 applyLayout 自动调整布局。
这和手动布局的流程是同样的,能够看出来 yoga 本质上也是手动布局,只是不再用手算坐标了。
yoga 同时也有很好的易用性,好比要实现一个简单的九宫格,只须要简单的设置一下布局参数。
override init(frame: CGRect) {
super.init(frame: frame)
configureLayout { (layout) in
layout.isEnabled = true
}
contentView = UIView(frame: bounds)
addSubview(contentView)
contentView.configureLayout { (layout) in
layout.isEnabled = true
layout.flexDirection = .row
layout.flexWrap = .wrap
layout.flexGrow = 1
}
for _ in 0...8 {
let imageView = UIImageView(frame: .zero)
imageView.backgroundColor = .orange
contentView.addSubview(imageView)
imageView.configureLayout { (layout) in
layout.isEnabled = true
layout.width = 86
layout.height = 86
layout.marginTop = 10
layout.marginLeft = 10
}
}
}
override func layoutSubviews() {
super.layoutSubviews()
yoga.applyLayout(preservingOrigin: true)
}
复制代码
核心参数是 layout.flexWrap = .wrap ,让视图布局自动换行,再计算好间距和宽高,这样就实现了九宫格的排列效果。
运行的效果: