首發於公眾號
在 iOS 中官方支援的佈局方式是 AutoLayout,是一種基於控制元件之間相互約束關係的自動佈局工具。
官方的 AutoLayout 雖然用起來簡單,但是有兩個非常不方便的地方:
- 原生 API 介面使用不友好
- 約束越多效能損失越多
第1個問題可以使用第三方庫來解決,比如 SnapKit(swift)、Masonry(oc)。 效能問題則無解,對於混合佈局的 Cell 如果全部使用自動佈局就會看到很明顯的滑動卡頓。
對於複雜 Cell 佈局,程式設計師們為了追求極致的幀率,一般都採用手寫佈局,幀率是上去了而維護的成本也最高。
為了兼顧易用性和高效率,Facebook 開發並開源了自己的佈局庫:Yoga。
Yoga 是 FlexBox 的子集,並沒有全部實現 FlexBox,但是對於大部分應用場景已經足夠了。
接觸過前端開發的朋友對 FlexBox 佈局一定不陌生,CSS 寫 flex 佈局真的太方便了。
FlexBox 是不同於 AutoLayout 的佈局方式,FlexBox 是自約束,每個控制元件的位置都是相對於自身所在的 Box 相對佈局,這就不存在 AutoLayout 基於控制元件間約束的耦合。
Yoga 是基於手動佈局的方式,這樣效率就很高,而且效能損耗很小,而且使用很簡單,用過 Masonry 的同學可以很快上手。
使用方法:
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 ,讓檢視佈局自動換行,再計算好間距和寬高,這樣就實現了九宮格的排列效果。
執行的效果: