I want to get the following structure programmatically (and am currently failing...):
- View
- Scroll View
- Vertical Stack View
- Scroll View
I was able to get what I wanted in Interface Builder, but cannot seem to figure out how to achieve this in code. In IB, it looks like this (please click on the picture to see it fully):
The settings of the stack view look like this:
Now, this is my attempt to mirror that in code:
import UIKit
class ScrollViewController: UIViewController {
lazy var scrollView: UIScrollView = {
let s = UIScrollView()
s.contentMode = .scaleToFill
s.backgroundColor = .gray
s.accessibilityIdentifier = "scroll_view"
s.translatesAutoresizingMaskIntoConstraints = false
return s
}()
lazy var stackView: UIStackView = {
let s = UIStackView()
s.axis = .vertical
s.alignment = .fill
s.distribution = .equalSpacing
s.spacing = 10
s.contentMode = .scaleToFill
s.accessibilityIdentifier = "stack_view"
return s
}()
// See helper method at bottom
lazy var textField1 = self.createTextField(placeholder: "Textfield 1")
lazy var textField2 = self.createTextField(placeholder: "Textfield 2")
lazy var textField3 = self.createTextField(placeholder: "Textfield 3")
lazy var textField4 = self.createTextField(placeholder: "Textfield 4")
lazy var textField5 = self.createTextField(placeholder: "Textfield 5")
lazy var textField6 = self.createTextField(placeholder: "Textfield 6")
override func loadView() {
view = UIView()
view.backgroundColor = .white
view.addSubview(scrollView)
scrollView.addSubview(stackView)
stackView.addArrangedSubview(textField1)
stackView.addArrangedSubview(textField2)
stackView.addArrangedSubview(textField3)
stackView.addArrangedSubview(textField4)
stackView.addArrangedSubview(textField5)
stackView.addArrangedSubview(textField6)
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20),
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20),
stackView.widthAnchor.constraint(equalTo: scrollView.contentLayoutGuide.widthAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
stackView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor)
])
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.contentSize = stackView.frame.size
}
func createTextField(placeholder: String) -> UITextField {
let t = UITextField()
t.translatesAutoresizingMaskIntoConstraints = false
t.borderStyle = .roundedRect
t.clearButtonMode = .whileEditing
t.text = placeholder
t.placeholder = placeholder
t.accessibilityIdentifier = placeholder
return t
}
}
I am quite obviously missing something, but even after spending several hours of trying and googling, I still haven't found a solution...
What I do realize is that all the text fields' and the stack view's frames are (0, 0, 0, 0), so quite obviously, I am missing some constraints, right?