背景
UIStackView在布局方面有很多優(yōu)勢,能減少很多布局的麻煩,但是自帶提供的方法過少,也很難用,這里提供幾種好用的擴展方法。充分發(fā)揮線性布局的優(yōu)勢。
使用演示

示例代碼
代碼實現(xiàn)
基礎擴展
import UIKit
extension UIStackView {
/// 移除所有子視圖
func removeAllArrangedSubviews() {
for subview in arrangedSubviews {
removeArrangedSubview(subview)
subview.removeFromSuperview()
}
}
/// 設置子視圖
func setArrangedSubviews(_ views: [UIView]) {
removeAllArrangedSubviews()
views.forEach { view in
addArrangedSubview(view)
}
}
/// 移除隱藏的視圖
func removeHiddenArrangedSubviews() {
for subview in arrangedSubviews {
if subview.isHidden {
removeArrangedSubview(subview)
subview.removeFromSuperview()
}else {
// 判斷子視圖是否為UIStackView, 里面的也移除
if let subStackView = subview as? UIStackView,
subStackView.arrangedSubviews.count > 0 {
subStackView.removeHiddenArrangedSubviews()
// 判斷如果沒有的話,就將自己移除
if subStackView.arrangedSubviews.count == 0 {
removeArrangedSubview(subStackView)
subStackView.removeFromSuperview()
}
}
}
}
}
}
快捷初始化
// MARK: - 快捷初始化
extension UIStackView {
convenience init(_ axis: NSLayoutConstraint.Axis,
spacing: CGFloat,
distribution: Distribution = .fill,
alignment: Alignment = .center,
content: (() -> [UIView])? = nil) {
self.init(arrangedSubviews: content?() ?? [])
self.axis = axis
self.spacing = spacing
self.distribution = distribution
self.alignment = alignment
}
}
設置視圖大小
// MARK: - UIView視圖大小
extension UIView {
/// 設置視圖大小
@discardableResult
func frame(width: CGFloat? = nil, height: CGFloat? = nil) -> Self {
self.snp.makeConstraints { make in
if let width = width {
make.width.equalTo(width)
}
if let height = height {
make.height.equalTo(height)
}
}
return self
}
}
內部占位視圖
由于自帶的間距不是很好用,這里提供一種自定義間距的視圖,spacing不傳為填充,傳了則有具體大小。這里學習的是SwiftUI中的布局方式。
// MARK: 內部類
extension UIStackView {
/// 占位視圖
func spacingView(_ spacing: CGFloat? = nil) -> SpacingView {
return SpacingView.init(axis, spacing)
}
/// 占位空視圖
class SpacingView: UIView {
init(_ axis: NSLayoutConstraint.Axis, _ spacing: CGFloat? = nil) {
super.init(frame: .zero)
if let spacing = spacing {
self.snp.makeConstraints { make in
switch axis {
case .horizontal:
make.width.equalTo(spacing)
case .vertical:
make.height.equalTo(spacing)
}
}
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
}
總結
優(yōu)點:
- 適用于固定線性布局,能夠快速布局
- 減少嵌套UIStackView命名煩惱
- 只是對原生UI的擴展,支持原生布局方式,方便兼容
缺點:
- 嵌套層級較深,閱讀較為困難