我的目标是创建一个堆栈视图,它可以容纳任意(~5-10)排列的子视图,并且如果它的高度变得比其包含的视图高,则变为可滚动。为此,我使用滚动视图。
我的理解是,如果每个排列的子视图都有明确的高度约束,那么distribution
设置为fill
的堆栈视图应具有内在内容大小。所以我可以将堆栈视图添加到滚动视图中,滚动可以从堆栈视图的内在内容大小中获取其内容大小。
我也试图让这个滚动堆栈视图对帧中的变化(来自键盘)具有鲁棒性。
我花了很多时间阅读很多关于Scroll View和StackView以及所有编程指南的长篇文章但却无法让它完美地运作。
以下代码及其略有变化的内容始终为content size is ambiguous
或Height is ambiguous for Scroll View
。当键盘弹出时(点击堆栈视图中的文本视图)我只是从Scroll View的底部约束常量中减去400。我的想法是Scroll View的框架/边界将变得小于Stack View的内在内容高度,并且会发生滚动。但是,屏幕只是空白。控制台中没有约束记录。
我花了很多时间思考这个场景中的所有考虑因素,但它似乎超出了我的范围。我非常感谢任何有关Stack View的Scroll Views主题的帮助或指示。
以下是我目前的实验:
class ViewController: UIViewController {
let scrollView = UIScrollView()
var scrollViewBottomConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
// stack view setup (one blue and hellow view at 100 height)
let stackView = UIStackView()
stackView.distribution = .fill
stackView.axis = .vertical
let v1 = UIView()
v1.backgroundColor = .blue
let v2 = UITextView()
v2.backgroundColor = .yellow
stackView.addArrangedSubview(v1)
stackView.addArrangedSubview(v2)
// scroll
scrollView.addSubview(stackView)
view.addSubview(scrollView)
// constraints for stack view arranged views
v1.heightAnchor.constraint(equalToConstant: 100).isActive = true
v2.heightAnchor.constraint(equalToConstant: 100).isActive = true
// pin scroll view in main view
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
// pin scroll view to stack view's bottom anchor
scrollViewBottomConstraint = scrollView.bottomAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 0)
scrollViewBottomConstraint.isActive = true
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 0).isActive = true
stackView.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 0).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0).isActive = true
// constrain "content view to main view and not scroll view."
stackView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1).isActive = true
NotificationCenter.default.addObserver(self,
selector: #selector(ViewController.handleKeyboard),
name: Notification.Name.UIKeyboardWillShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(ViewController.handleKeyboard),
name: Notification.Name.UIKeyboardWillHide,
object: nil)
}
func handleKeyboard(notification: Notification) {
scrollViewBottomConstraint.constant = -400
}
}
答案 0 :(得分:0)
我在这里添加我的工作示例:
class ViewController: UIViewController {
let scrollView = UIScrollView()
var scrollViewBottomConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
// stack view setup (one blue and hellow view at 100 height)
let stackView = UIStackView()
stackView.distribution = .fill
stackView.axis = .vertical
let v1 = UIView()
v1.backgroundColor = .blue
let v2 = UITextView()
v2.backgroundColor = .yellow
let v3 = UITextView()
v3.backgroundColor = .green
let v4 = UITextView()
v4.backgroundColor = .brown
stackView.addArrangedSubview(v1)
stackView.addArrangedSubview(v2)
stackView.addArrangedSubview(v3)
stackView.addArrangedSubview(v4)
// scroll
scrollView.addSubview(stackView)
view.addSubview(scrollView)
// constraints for stack view arranged views
v1.heightAnchor.constraint(equalToConstant: 200).isActive = true
v2.heightAnchor.constraint(equalToConstant: 200).isActive = true
v3.heightAnchor.constraint(equalToConstant: 180).isActive = true
v4.heightAnchor.constraint(equalToConstant: 250).isActive = true
// pin scroll view in main view
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 100).isActive = true
// pin scroll view to stack view's bottom anchor
scrollViewBottomConstraint = scrollView.bottomAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 0)
scrollViewBottomConstraint.isActive = true
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 0).isActive = true
stackView.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 0).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0).isActive = true
// constrain "content view to main view and not scroll view."
stackView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1).isActive = true
NotificationCenter.default.addObserver(self,
selector: #selector(ViewController.handleKeyboard),
name: Notification.Name.UIKeyboardWillShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(ViewController.handleKeyboard),
name: Notification.Name.UIKeyboardWillHide,
object: nil)
}
func handleKeyboard(notification: Notification) {
scrollViewBottomConstraint.constant = -400
}
}