Вид / размер прокрутки всегда неоднозначны, когда содержат вид стека
Моя цель - создать Stack View, который может содержать произвольные (~5-10) упорядоченные подпредставления и стать прокручиваемым, если его высота станет выше, чем представление, содержащееся в нем. Для этого я использую представление прокрутки.
Я понимаю, что Stack View которого distribution
установлен в fill
должен иметь внутренний размер контента, если каждое упорядоченное подпредставление имеет явное ограничение по высоте. Таким образом, я могу добавить представление стека к представлению прокрутки, и прокрутка может получить размер своего содержимого из собственного размера содержимого представления стека.
Я также пытаюсь сделать просмотр стека прокрутки устойчивым к изменениям в кадре (с клавиатуры).
Я потратил много времени и прочитал много длинных статей о Scroll View и StackView и всех руководствах по программированию, но не могу заставить его работать идеально.
Следующий код и небольшие изменения в нем всегда дают content size is ambiguous
или же Height is ambiguous for Scroll View
, Когда клавиатура всплывает (от нажатия на текстовое представление в представлении стека), я просто вычитаю 400 из константы нижнего ограничения представления прокрутки. Я думаю, что рамка / границы представления прокрутки станут меньше, чем внутренняя высота содержимого представления стека, и произойдет прокрутка. Однако экран просто гаснет. В консоли также нет журналов ограничений.
Я потратил очень много времени на обдумывание всех соображений в этом сценарии, но он кажется мне просто не по силам. Я был бы очень признателен за любую помощь или указатели по теме 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
}
}
1 ответ
Я добавляю сюда мой рабочий пример:
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
}
}