Scrollview 中的两个动态 Stackview
Two dynamic Stackviews in Scrollview
这是我的视图层次结构
ScrollView
-> View
-> Stackview1
-> view1
-> view2
.
.
.
-> Stackview1
-> view1
-> view2
.
.
.
所以这里我的 stackview 的高度是根据添加到 .swift 文件
上的视图动态生成的
如果我为超级视图提供底部约束,它只适用于单个堆栈视图,但如果我使用两个堆栈视图,则不会考虑第二个堆栈视图。
很难说出问题是什么,因为您还没有发布约束条件,但解决方案非常简单:
您需要以下限制条件:
滚动视图:
topAnchor
至 view.topAnchor
leadingAnchor
到 view.leadingAnchor
trailingAnchor
到 view.trailingAnchor
bottomAnchor
至 view.bottomAnchor
包装 2 个 UIStackView 的 UIView:
topAnchor
到 scrollView.topAnchor
leadingAnchor
到 scrollView.leadingAnchor
trailingAnchor
到 scrollView.trailingAnchor
bottomAnchor
到 scrollView.bottomAnchor
上层 StackView:
topAnchor
至 wrapperView.topAnchor
leadingAnchor
到 wrapperView.leadingAnchor
trailingAnchor
到 wrapperView.trailingAnchor
widthAnchor
到scrollView.widthAnchor
(定义ScrollView的宽度contentSize
)
下 StackView:
topAnchor
至 upperStackView.bottomAnchor
leadingAnchor
到 wrapperView.leadingAnchor
trailingAnchor
到 wrapperView.trailingAnchor
bottomAnchor
到 wrapperView.bottomAnchor
现在,当您将 UIView
添加到 UIStackViews
之一时,UIScrollView 会自动更新。
这是一个工作示例:(我添加了两个 UIButtons
以向两个 UIStackViews
添加更多 UIViews
)
class ViewController: UIViewController {
let upperStackView = UIStackView()
let lowerStackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
let scrollView = UIScrollView()
view.addSubview(scrollView)
scrollView.backgroundColor = .white
scrollView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
let wrapperView = UIView()
scrollView.addSubview(wrapperView)
wrapperView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
wrapperView.topAnchor.constraint(equalTo: scrollView.topAnchor),
wrapperView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
wrapperView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
wrapperView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
])
upperStackView.axis = .vertical
upperStackView.distribution = .equalSpacing
upperStackView.alignment = .fill
wrapperView.addSubview(upperStackView)
upperStackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
upperStackView.topAnchor.constraint(equalTo: wrapperView.topAnchor),
upperStackView.leadingAnchor.constraint(equalTo: wrapperView.leadingAnchor),
upperStackView.trailingAnchor.constraint(equalTo: wrapperView.trailingAnchor),
upperStackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
])
lowerStackView.axis = .vertical
lowerStackView.distribution = .equalSpacing
lowerStackView.alignment = .fill
wrapperView.addSubview(lowerStackView)
lowerStackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
lowerStackView.topAnchor.constraint(equalTo: upperStackView.bottomAnchor),
lowerStackView.leadingAnchor.constraint(equalTo: wrapperView.leadingAnchor),
lowerStackView.trailingAnchor.constraint(equalTo: wrapperView.trailingAnchor),
lowerStackView.bottomAnchor.constraint(equalTo: wrapperView.bottomAnchor)
])
for _ in 0...3 {
addView(to: upperStackView)
addView(to: lowerStackView)
}
let lowerButton = UIButton(type: .system)
lowerButton.setTitle("Add to lower StackView", for: .normal)
lowerButton.backgroundColor = .white
lowerButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(lowerButton)
NSLayoutConstraint.activate([
lowerButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -60),
lowerButton.widthAnchor.constraint(equalToConstant: 240),
lowerButton.heightAnchor.constraint(equalToConstant: 44),
lowerButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
lowerButton.addTarget(self, action: #selector(addViewToLowerStackView), for: .touchUpInside)
let upperButton = UIButton(type: .system)
upperButton.setTitle("Add to upper StackView", for: .normal)
upperButton.backgroundColor = .white
upperButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(upperButton)
NSLayoutConstraint.activate([
upperButton.bottomAnchor.constraint(equalTo: lowerButton.topAnchor, constant: -20),
upperButton.widthAnchor.constraint(equalToConstant: 240),
upperButton.heightAnchor.constraint(equalToConstant: 44),
upperButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
upperButton.addTarget(self, action: #selector(addViewToUpperStackView), for: .touchUpInside)
}
func addView(to stackView: UIStackView) {
let view = UIView()
view.backgroundColor = stackView == upperStackView ? .blue : .green
view.alpha = CGFloat(stackView.arrangedSubviews.count + 1) * 0.1
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([view.heightAnchor.constraint(equalToConstant: 120)])
stackView.addArrangedSubview(view)
}
@objc func addViewToUpperStackView() {
addView(to: upperStackView)
}
@objc func addViewToLowerStackView() {
addView(to: lowerStackView)
}
}
更新:
您也可以仅使用情节提要来完成这项工作:
这是我的视图层次结构
ScrollView
-> View
-> Stackview1
-> view1
-> view2
.
.
.
-> Stackview1
-> view1
-> view2
.
.
.
所以这里我的 stackview 的高度是根据添加到 .swift 文件
上的视图动态生成的如果我为超级视图提供底部约束,它只适用于单个堆栈视图,但如果我使用两个堆栈视图,则不会考虑第二个堆栈视图。
很难说出问题是什么,因为您还没有发布约束条件,但解决方案非常简单:
您需要以下限制条件:
滚动视图:
topAnchor
至view.topAnchor
leadingAnchor
到view.leadingAnchor
trailingAnchor
到view.trailingAnchor
bottomAnchor
至view.bottomAnchor
包装 2 个 UIStackView 的 UIView:
topAnchor
到scrollView.topAnchor
leadingAnchor
到scrollView.leadingAnchor
trailingAnchor
到scrollView.trailingAnchor
bottomAnchor
到scrollView.bottomAnchor
上层 StackView:
topAnchor
至wrapperView.topAnchor
leadingAnchor
到wrapperView.leadingAnchor
trailingAnchor
到wrapperView.trailingAnchor
widthAnchor
到scrollView.widthAnchor
(定义ScrollView的宽度contentSize
)
下 StackView:
topAnchor
至upperStackView.bottomAnchor
leadingAnchor
到wrapperView.leadingAnchor
trailingAnchor
到wrapperView.trailingAnchor
bottomAnchor
到wrapperView.bottomAnchor
现在,当您将 UIView
添加到 UIStackViews
之一时,UIScrollView 会自动更新。
这是一个工作示例:(我添加了两个 UIButtons
以向两个 UIStackViews
添加更多 UIViews
)
class ViewController: UIViewController {
let upperStackView = UIStackView()
let lowerStackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
let scrollView = UIScrollView()
view.addSubview(scrollView)
scrollView.backgroundColor = .white
scrollView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
let wrapperView = UIView()
scrollView.addSubview(wrapperView)
wrapperView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
wrapperView.topAnchor.constraint(equalTo: scrollView.topAnchor),
wrapperView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
wrapperView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
wrapperView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
])
upperStackView.axis = .vertical
upperStackView.distribution = .equalSpacing
upperStackView.alignment = .fill
wrapperView.addSubview(upperStackView)
upperStackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
upperStackView.topAnchor.constraint(equalTo: wrapperView.topAnchor),
upperStackView.leadingAnchor.constraint(equalTo: wrapperView.leadingAnchor),
upperStackView.trailingAnchor.constraint(equalTo: wrapperView.trailingAnchor),
upperStackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
])
lowerStackView.axis = .vertical
lowerStackView.distribution = .equalSpacing
lowerStackView.alignment = .fill
wrapperView.addSubview(lowerStackView)
lowerStackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
lowerStackView.topAnchor.constraint(equalTo: upperStackView.bottomAnchor),
lowerStackView.leadingAnchor.constraint(equalTo: wrapperView.leadingAnchor),
lowerStackView.trailingAnchor.constraint(equalTo: wrapperView.trailingAnchor),
lowerStackView.bottomAnchor.constraint(equalTo: wrapperView.bottomAnchor)
])
for _ in 0...3 {
addView(to: upperStackView)
addView(to: lowerStackView)
}
let lowerButton = UIButton(type: .system)
lowerButton.setTitle("Add to lower StackView", for: .normal)
lowerButton.backgroundColor = .white
lowerButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(lowerButton)
NSLayoutConstraint.activate([
lowerButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -60),
lowerButton.widthAnchor.constraint(equalToConstant: 240),
lowerButton.heightAnchor.constraint(equalToConstant: 44),
lowerButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
lowerButton.addTarget(self, action: #selector(addViewToLowerStackView), for: .touchUpInside)
let upperButton = UIButton(type: .system)
upperButton.setTitle("Add to upper StackView", for: .normal)
upperButton.backgroundColor = .white
upperButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(upperButton)
NSLayoutConstraint.activate([
upperButton.bottomAnchor.constraint(equalTo: lowerButton.topAnchor, constant: -20),
upperButton.widthAnchor.constraint(equalToConstant: 240),
upperButton.heightAnchor.constraint(equalToConstant: 44),
upperButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
upperButton.addTarget(self, action: #selector(addViewToUpperStackView), for: .touchUpInside)
}
func addView(to stackView: UIStackView) {
let view = UIView()
view.backgroundColor = stackView == upperStackView ? .blue : .green
view.alpha = CGFloat(stackView.arrangedSubviews.count + 1) * 0.1
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([view.heightAnchor.constraint(equalToConstant: 120)])
stackView.addArrangedSubview(view)
}
@objc func addViewToUpperStackView() {
addView(to: upperStackView)
}
@objc func addViewToLowerStackView() {
addView(to: lowerStackView)
}
}
更新:
您也可以仅使用情节提要来完成这项工作: