首發(fā)于公眾號(hào)
在 iOS 中官方支持的布局方式是 AutoLayout,是一種基于控件之間相互約束關(guān)系的自動(dòng)布局工具。
官方的 AutoLayout 雖然用起來(lái)簡(jiǎn)單,但是有兩個(gè)非常不方便的地方:
- 原生 API 接口使用不友好
- 約束越多性能損失越多
第1個(gè)問(wèn)題可以使用第三方庫(kù)來(lái)解決,比如 SnapKit(swift)、Masonry(oc)。
性能問(wèn)題則無(wú)解,對(duì)于混合布局的 Cell 如果全部使用自動(dòng)布局就會(huì)看到很明顯的滑動(dòng)卡頓。
對(duì)于復(fù)雜 Cell 布局,程序員們?yōu)榱俗非髽O致的幀率,一般都采用手寫布局,幀率是上去了而維護(hù)的成本也最高。
為了兼顧易用性和高效率,F(xiàn)acebook 開(kāi)發(fā)并開(kāi)源了自己的布局庫(kù):Yoga。
Yoga 是 FlexBox 的子集,并沒(méi)有全部實(shí)現(xiàn) FlexBox,但是對(duì)于大部分應(yīng)用場(chǎng)景已經(jīng)足夠了。
接觸過(guò)前端開(kāi)發(fā)的朋友對(duì) FlexBox 布局一定不陌生,CSS 寫 flex 布局真的太方便了。
FlexBox 是不同于 AutoLayout 的布局方式,F(xiàn)lexBox 是自約束,每個(gè)控件的位置都是相對(duì)于自身所在的 Box 相對(duì)布局,這就不存在 AutoLayout 基于控件間約束的耦合。
Yoga 是基于手動(dòng)布局的方式,這樣效率就很高,而且性能損耗很小,而且使用很簡(jiǎn)單,用過(guò) Masonry 的同學(xué)可以很快上手。
使用方法:
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 開(kāi)啟 yoga 布局,
在 layoutSubviews 中使用 applyLayout 自動(dòng)調(diào)整布局。
這和手動(dòng)布局的流程是一樣的,可以看出來(lái) yoga 本質(zhì)上也是手動(dòng)布局,只是再也不用手算坐標(biāo)了。
yoga 同時(shí)也有很好的易用性,比如要實(shí)現(xiàn)一個(gè)簡(jiǎn)單的九宮格,只需要簡(jiǎn)單的設(shè)置一下布局參數(shù)。
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)
}
核心參數(shù)是 layout.flexWrap = .wrap ,讓視圖布局自動(dòng)換行,再計(jì)算好間距和寬高,這樣就實(shí)現(xiàn)了九宮格的排列效果。
運(yùn)行的效果: