如何在 ScrollView 中布局 2 个不同大小的 StackView
How to layout 2 StackView of different sizes in a ScrollView
我正在尝试将 2 个 stackView
合二为一 ScrollView
我决定创建一个包含其他两个 StackViews
的通用 StackView
并将其放在 ScrollView
中
但是我的左边 StackView
包含 1 个项目,第二个包含 2 个项目
代码如下:
let categoryViewsForLeftColumn = categoryViews.split()[0]
let categoryViewsForRightColumn = categoryViews.split()[1]
let leftColumnStackView = UIStackView(arrangedSubviews: categoryViewsForLeftColumn)
leftColumnStackView.translatesAutoresizingMaskIntoConstraints = false
leftColumnStackView.axis = .vertical
leftColumnStackView.spacing = 20
leftColumnStackView.distribution = .fillEqually
let rightColumnStackView = UIStackView(arrangedSubviews: categoryViewsForRightColumn)
rightColumnStackView.translatesAutoresizingMaskIntoConstraints = false
rightColumnStackView.axis = .vertical
rightColumnStackView.spacing = 20
rightColumnStackView.distribution = .fillEqually
let generalStackView = UIStackView(arrangedSubviews: [leftColumnStackView, rightColumnStackView])
generalStackView.translatesAutoresizingMaskIntoConstraints = false
generalStackView.axis = .horizontal
generalStackView.spacing = 20
generalStackView.distribution = .fillEqually
categoriesScrollView.addSubview(generalStackView)
leftColumnStackView.backgroundColor = .green
rightColumnStackView.backgroundColor = .red
NSLayoutConstraint.activate([
generalStackView.widthAnchor.constraint(equalTo: categoriesScrollView.widthAnchor, constant: -10),
generalStackView.leadingAnchor.constraint(equalTo: categoriesScrollView.leadingAnchor, constant: 5),
generalStackView.trailingAnchor.constraint(equalTo: categoriesScrollView.trailingAnchor, constant: -5),
generalStackView.topAnchor.constraint(equalTo: categoriesScrollView.topAnchor, constant: 5),
generalStackView.bottomAnchor.constraint(equalTo: categoriesScrollView.bottomAnchor, constant: -5)
])
结果如下:
我希望商品尺寸相同
我正在尝试 post 2 StackView 到 ScrollView
代码如下:
categoriesScrollView.addSubview(leftColumnStackView)
categoriesScrollView.addSubview(rightColumnStackView)
leftColumnStackView.backgroundColor = .green
rightColumnStackView.backgroundColor = .red
NSLayoutConstraint.activate([
leftColumnStackView.leadingAnchor.constraint(equalTo: categoriesScrollView.leadingAnchor, constant: 5),
leftColumnStackView.trailingAnchor.constraint(equalTo: categoriesScrollView.centerXAnchor, constant: -5),
leftColumnStackView.topAnchor.constraint(equalTo: categoriesScrollView.topAnchor, constant: 5),
leftColumnStackView.bottomAnchor.constraint(equalTo: categoriesScrollView.bottomAnchor, constant: -5),
rightColumnStackView.leadingAnchor.constraint(equalTo: categoriesScrollView.centerXAnchor, constant: 5),
rightColumnStackView.trailingAnchor.constraint(equalTo: categoriesScrollView.trailingAnchor, constant: -5),
rightColumnStackView.topAnchor.constraint(equalTo: categoriesScrollView.topAnchor, constant: 5),
rightColumnStackView.bottomAnchor.constraint(equalTo: categoriesScrollView.bottomAnchor, constant: -5)
])
但情况只会变得更糟
结果如下:
我想要达到的结果:
有人知道如何实现吗?
如果你想创建一个像 那样的“网格”而不是 使用集合视图(并且有很多不这样做的充分理由),你可以使用堆栈视图来完成。
但是,与其考虑具有两个垂直“列”堆栈视图的水平堆栈视图,不如考虑具有“行”水平堆栈视图的垂直堆栈视图。
这是一个简单的例子...
首先,一个带有圆边的自定义视图、一个图像视图和一个标签:
class PillView: UIView {
let imgView = UIImageView()
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
label.numberOfLines = 0
imgView.translatesAutoresizingMaskIntoConstraints = false
label.translatesAutoresizingMaskIntoConstraints = false
addSubview(imgView)
addSubview(label)
NSLayoutConstraint.activate([
imgView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16.0),
imgView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: 12.0),
imgView.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: -12.0),
imgView.centerYAnchor.constraint(equalTo: centerYAnchor),
imgView.widthAnchor.constraint(equalToConstant: 36.0),
imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor),
label.topAnchor.constraint(equalTo: topAnchor, constant: 8.0),
label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8.0),
label.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 8.0),
label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16.0),
])
layer.borderColor = UIColor.lightGray.cgColor
layer.borderWidth = 1
}
override var bounds: CGRect {
get { return super.bounds }
set(newBounds) {
super.bounds = newBounds
layer.cornerRadius = newBounds.size.height / 2.0
}
}
}
现在,一个示例控制器:
class SampleViewController: UIViewController {
let numViews: Int = 5
override func viewDidLoad() {
super.viewDidLoad()
let outerVerticalStack = UIStackView()
outerVerticalStack.axis = .vertical
outerVerticalStack.spacing = 20
outerVerticalStack.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(outerVerticalStack)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
outerVerticalStack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
outerVerticalStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
outerVerticalStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
])
var j: Int = 0
while j < numViews {
let rowStack = UIStackView()
rowStack.axis = .horizontal
rowStack.spacing = 20
rowStack.distribution = .fillEqually
let v = PillView()
if j == 2 {
v.label.text = "View \(j)\ntwo lines"
} else {
v.label.text = "View \(j)"
}
if let img = UIImage(systemName: "\(j).square.fill") {
v.imgView.image = img
}
rowStack.addArrangedSubview(v)
j += 1
if j < numViews {
let v = PillView()
v.label.text = "View \(j)"
if let img = UIImage(systemName: "\(j).square.fill") {
v.imgView.image = img
}
rowStack.addArrangedSubview(v)
} else {
let v = UIView()
rowStack.addArrangedSubview(v)
}
j += 1
outerVerticalStack.addArrangedSubview(rowStack)
}
}
}
结果如下所示:
我正在尝试将 2 个 stackView
合二为一 ScrollView
我决定创建一个包含其他两个 StackViews
的通用 StackView
并将其放在 ScrollView
但是我的左边 StackView
包含 1 个项目,第二个包含 2 个项目
代码如下:
let categoryViewsForLeftColumn = categoryViews.split()[0]
let categoryViewsForRightColumn = categoryViews.split()[1]
let leftColumnStackView = UIStackView(arrangedSubviews: categoryViewsForLeftColumn)
leftColumnStackView.translatesAutoresizingMaskIntoConstraints = false
leftColumnStackView.axis = .vertical
leftColumnStackView.spacing = 20
leftColumnStackView.distribution = .fillEqually
let rightColumnStackView = UIStackView(arrangedSubviews: categoryViewsForRightColumn)
rightColumnStackView.translatesAutoresizingMaskIntoConstraints = false
rightColumnStackView.axis = .vertical
rightColumnStackView.spacing = 20
rightColumnStackView.distribution = .fillEqually
let generalStackView = UIStackView(arrangedSubviews: [leftColumnStackView, rightColumnStackView])
generalStackView.translatesAutoresizingMaskIntoConstraints = false
generalStackView.axis = .horizontal
generalStackView.spacing = 20
generalStackView.distribution = .fillEqually
categoriesScrollView.addSubview(generalStackView)
leftColumnStackView.backgroundColor = .green
rightColumnStackView.backgroundColor = .red
NSLayoutConstraint.activate([
generalStackView.widthAnchor.constraint(equalTo: categoriesScrollView.widthAnchor, constant: -10),
generalStackView.leadingAnchor.constraint(equalTo: categoriesScrollView.leadingAnchor, constant: 5),
generalStackView.trailingAnchor.constraint(equalTo: categoriesScrollView.trailingAnchor, constant: -5),
generalStackView.topAnchor.constraint(equalTo: categoriesScrollView.topAnchor, constant: 5),
generalStackView.bottomAnchor.constraint(equalTo: categoriesScrollView.bottomAnchor, constant: -5)
])
结果如下:
我希望商品尺寸相同
我正在尝试 post 2 StackView 到 ScrollView
代码如下:
categoriesScrollView.addSubview(leftColumnStackView)
categoriesScrollView.addSubview(rightColumnStackView)
leftColumnStackView.backgroundColor = .green
rightColumnStackView.backgroundColor = .red
NSLayoutConstraint.activate([
leftColumnStackView.leadingAnchor.constraint(equalTo: categoriesScrollView.leadingAnchor, constant: 5),
leftColumnStackView.trailingAnchor.constraint(equalTo: categoriesScrollView.centerXAnchor, constant: -5),
leftColumnStackView.topAnchor.constraint(equalTo: categoriesScrollView.topAnchor, constant: 5),
leftColumnStackView.bottomAnchor.constraint(equalTo: categoriesScrollView.bottomAnchor, constant: -5),
rightColumnStackView.leadingAnchor.constraint(equalTo: categoriesScrollView.centerXAnchor, constant: 5),
rightColumnStackView.trailingAnchor.constraint(equalTo: categoriesScrollView.trailingAnchor, constant: -5),
rightColumnStackView.topAnchor.constraint(equalTo: categoriesScrollView.topAnchor, constant: 5),
rightColumnStackView.bottomAnchor.constraint(equalTo: categoriesScrollView.bottomAnchor, constant: -5)
])
但情况只会变得更糟
结果如下:
我想要达到的结果:
有人知道如何实现吗?
如果你想创建一个像 那样的“网格”而不是 使用集合视图(并且有很多不这样做的充分理由),你可以使用堆栈视图来完成。
但是,与其考虑具有两个垂直“列”堆栈视图的水平堆栈视图,不如考虑具有“行”水平堆栈视图的垂直堆栈视图。
这是一个简单的例子...
首先,一个带有圆边的自定义视图、一个图像视图和一个标签:
class PillView: UIView {
let imgView = UIImageView()
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
label.numberOfLines = 0
imgView.translatesAutoresizingMaskIntoConstraints = false
label.translatesAutoresizingMaskIntoConstraints = false
addSubview(imgView)
addSubview(label)
NSLayoutConstraint.activate([
imgView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16.0),
imgView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: 12.0),
imgView.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: -12.0),
imgView.centerYAnchor.constraint(equalTo: centerYAnchor),
imgView.widthAnchor.constraint(equalToConstant: 36.0),
imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor),
label.topAnchor.constraint(equalTo: topAnchor, constant: 8.0),
label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8.0),
label.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 8.0),
label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16.0),
])
layer.borderColor = UIColor.lightGray.cgColor
layer.borderWidth = 1
}
override var bounds: CGRect {
get { return super.bounds }
set(newBounds) {
super.bounds = newBounds
layer.cornerRadius = newBounds.size.height / 2.0
}
}
}
现在,一个示例控制器:
class SampleViewController: UIViewController {
let numViews: Int = 5
override func viewDidLoad() {
super.viewDidLoad()
let outerVerticalStack = UIStackView()
outerVerticalStack.axis = .vertical
outerVerticalStack.spacing = 20
outerVerticalStack.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(outerVerticalStack)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
outerVerticalStack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
outerVerticalStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
outerVerticalStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
])
var j: Int = 0
while j < numViews {
let rowStack = UIStackView()
rowStack.axis = .horizontal
rowStack.spacing = 20
rowStack.distribution = .fillEqually
let v = PillView()
if j == 2 {
v.label.text = "View \(j)\ntwo lines"
} else {
v.label.text = "View \(j)"
}
if let img = UIImage(systemName: "\(j).square.fill") {
v.imgView.image = img
}
rowStack.addArrangedSubview(v)
j += 1
if j < numViews {
let v = PillView()
v.label.text = "View \(j)"
if let img = UIImage(systemName: "\(j).square.fill") {
v.imgView.image = img
}
rowStack.addArrangedSubview(v)
} else {
let v = UIView()
rowStack.addArrangedSubview(v)
}
j += 1
outerVerticalStack.addArrangedSubview(rowStack)
}
}
}
结果如下所示: