背景
UIStackView在布局方面有很多优势,能减少很多布局的麻烦,但是自带提供的方法过少,也很难用,这里提供几种好用的扩展方法。充分发挥线性布局的优势。
使用演示
代码实现
基础扩展
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")
}
}
}
总结
优点:
- 适用于固定线性布局,能够快速布局
- 减少嵌套UIStackView命名烦恼
- 只是对原生UI的扩展,支持原生布局方式,方便兼容
缺点:
- 嵌套层级较深,阅读较为困难