UIStackView children 等距(周围和之间)
UIStackView children equally spaced (around and between)
如何让 UIStackView 具有 与 space 相同的填充和视图之间的间隙 ?
如何实现这种布局:
当这个不适合我时:
这也不行:
我只需要周围视图 space 与视图之间 space 相同。
为什么这么难?
重要
我正在使用 my fork of TZStackView 来支持 iOS 7。所以我没有 layoutMargins
:(
您几乎可以使用 UIStackView 实现您想要的效果。当您自己对 UIStackView 中的 UIViews 设置一些约束时,您可以想出这个:
这缺少您要查找的左右填充。问题是 UIStackView
在您向其添加视图时添加了自己的约束。在这种情况下,您可以添加 top
和 bottom
约束以获得垂直填充,但是当您尝试为右填充添加 trailing
约束时,UIStackView
会忽略或覆盖那个约束。有趣的是,为左侧填充添加一个 leading
约束。
但是对 UIStackView's
排列的子视图设置约束无论如何都不是你想要做的。使用 UIStackView
的全部意义在于只给它一些视图,让 UIStackView
处理其余的。
要实现你想要做的事情其实并不难。这是一个 UIViewController
的示例,其中包含可以处理所有边的填充的自定义堆栈视图(我使用 SnapKit 作为约束):
import UIKit
import SnapKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let padding: CGFloat = 30
let customStackView = UIView()
customStackView.backgroundColor = UIColor(white: 0, alpha: 0.1)
view.addSubview(customStackView)
customStackView.snp_makeConstraints { (make) -> Void in
make.top.left.equalTo(padding)
make.right.equalTo(-padding)
}
// define an array of subviews
let views = [UIView(), UIView(), UIView()]
// UIView does not have an intrinsic contentSize
// so you have to set some heights
// In a real implementation the height will be determined
// by the views' content, but for this example
// you have to set the height programmatically
views[0].snp_makeConstraints { (make) -> Void in
make.height.equalTo(150)
}
views[1].snp_makeConstraints { (make) -> Void in
make.height.equalTo(120)
}
views[2].snp_makeConstraints { (make) -> Void in
make.height.equalTo(130)
}
// Iterate through the views and set the constraints
var leftHandView: UIView? = nil
for view in views {
customStackView.addSubview(view)
view.backgroundColor = UIColor(white: 0, alpha: 0.15)
view.snp_makeConstraints(closure: { (make) -> Void in
make.top.equalTo(padding)
make.bottom.lessThanOrEqualTo(-padding)
if let leftHandView = leftHandView {
make.left.equalTo(leftHandView.snp_right).offset(padding)
make.width.equalTo(leftHandView)
} else {
make.left.equalTo(padding)
}
leftHandView = view
})
}
if let lastView = views.last {
lastView.snp_makeConstraints(closure: { (make) -> Void in
make.right.equalTo(-padding)
})
}
}
}
这会产生以下结果:
致那些不断来到这里寻找解决方案的人。我发现最好的方法(在我的例子中)是使用父 UIView
作为背景和填充,如下所示:
在这种情况下,UIStackView
使用填充限制在 UIView
的边缘,并使用间距分隔子视图。
我知道这是一个较老的问题,但我解决它的方法是在堆栈的开头和结尾添加两个大小为零的 UIView,然后使用 .equalSpacing
分布。
注意:这只能保证沿堆栈视图的主轴(即我的示例中的左右边缘)的周围间距相等
let stack = UIStackView()
stack.axis = .horizontal
stack.alignment = .center
stack.distribution = .equalSpacing
// add content normally
// ...
// add extra views for spacing
stack.insertArrangedSubview(UIView(), at: 0)
stack.addArrangedSubview(UIView())
如何让 UIStackView 具有 与 space 相同的填充和视图之间的间隙 ?
如何实现这种布局:
当这个不适合我时:
这也不行:
我只需要周围视图 space 与视图之间 space 相同。 为什么这么难?
重要
我正在使用 my fork of TZStackView 来支持 iOS 7。所以我没有 layoutMargins
:(
您几乎可以使用 UIStackView 实现您想要的效果。当您自己对 UIStackView 中的 UIViews 设置一些约束时,您可以想出这个:
这缺少您要查找的左右填充。问题是 UIStackView
在您向其添加视图时添加了自己的约束。在这种情况下,您可以添加 top
和 bottom
约束以获得垂直填充,但是当您尝试为右填充添加 trailing
约束时,UIStackView
会忽略或覆盖那个约束。有趣的是,为左侧填充添加一个 leading
约束。
但是对 UIStackView's
排列的子视图设置约束无论如何都不是你想要做的。使用 UIStackView
的全部意义在于只给它一些视图,让 UIStackView
处理其余的。
要实现你想要做的事情其实并不难。这是一个 UIViewController
的示例,其中包含可以处理所有边的填充的自定义堆栈视图(我使用 SnapKit 作为约束):
import UIKit
import SnapKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let padding: CGFloat = 30
let customStackView = UIView()
customStackView.backgroundColor = UIColor(white: 0, alpha: 0.1)
view.addSubview(customStackView)
customStackView.snp_makeConstraints { (make) -> Void in
make.top.left.equalTo(padding)
make.right.equalTo(-padding)
}
// define an array of subviews
let views = [UIView(), UIView(), UIView()]
// UIView does not have an intrinsic contentSize
// so you have to set some heights
// In a real implementation the height will be determined
// by the views' content, but for this example
// you have to set the height programmatically
views[0].snp_makeConstraints { (make) -> Void in
make.height.equalTo(150)
}
views[1].snp_makeConstraints { (make) -> Void in
make.height.equalTo(120)
}
views[2].snp_makeConstraints { (make) -> Void in
make.height.equalTo(130)
}
// Iterate through the views and set the constraints
var leftHandView: UIView? = nil
for view in views {
customStackView.addSubview(view)
view.backgroundColor = UIColor(white: 0, alpha: 0.15)
view.snp_makeConstraints(closure: { (make) -> Void in
make.top.equalTo(padding)
make.bottom.lessThanOrEqualTo(-padding)
if let leftHandView = leftHandView {
make.left.equalTo(leftHandView.snp_right).offset(padding)
make.width.equalTo(leftHandView)
} else {
make.left.equalTo(padding)
}
leftHandView = view
})
}
if let lastView = views.last {
lastView.snp_makeConstraints(closure: { (make) -> Void in
make.right.equalTo(-padding)
})
}
}
}
这会产生以下结果:
致那些不断来到这里寻找解决方案的人。我发现最好的方法(在我的例子中)是使用父 UIView
作为背景和填充,如下所示:
在这种情况下,UIStackView
使用填充限制在 UIView
的边缘,并使用间距分隔子视图。
我知道这是一个较老的问题,但我解决它的方法是在堆栈的开头和结尾添加两个大小为零的 UIView,然后使用 .equalSpacing
分布。
注意:这只能保证沿堆栈视图的主轴(即我的示例中的左右边缘)的周围间距相等
let stack = UIStackView()
stack.axis = .horizontal
stack.alignment = .center
stack.distribution = .equalSpacing
// add content normally
// ...
// add extra views for spacing
stack.insertArrangedSubview(UIView(), at: 0)
stack.addArrangedSubview(UIView())