Example:
class ViewController: UIViewController {
let labelOne: UIView = {
let label = UIView()
label.backgroundColor = .red
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .cyan
v.contentSize = CGSize(width: 2000, height: 2000)
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(scrollView)
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8.0).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8.0).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0).isActive = true
scrollView.addSubview(labelOne)
labelOne.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 16.0).isActive = true
labelOne.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 16.0).isActive = true
labelOne.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -16).isActive = true
labelOne.heightAnchor.constraint(equalToConstant: 100).isActive = true
}
}
P.s I know it would be better if I put the content view in a UIScrollView and build a view hierarchy in that content, but I'm genuinely wondering why this is happening
Take a look at this...
We set the labelOne
(red view):
.contentLayoutGuide
.contentLayoutGuide
So:
class ViewController: UIViewController {
let labelOne: UIView = {
let label = UIView()
label.backgroundColor = .red
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .cyan
// don't set this
//v.contentSize = CGSize(width: 2000, height: 2000)
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(scrollView)
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8.0).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8.0).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0).isActive = true
scrollView.addSubview(labelOne)
// don't constrain directly to scrollView
//labelOne.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 16.0).isActive = true
//labelOne.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 16.0).isActive = true
//labelOne.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -16).isActive = true
//labelOne.heightAnchor.constraint(equalToConstant: 100).isActive = true
// if we want horizontal scrolling of 2000-pts
// and labelOne to have 16-pts space on each side
labelOne.widthAnchor.constraint(equalToConstant: 2000.0 - 32.0).isActive = true
// labelOne height = 100
labelOne.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
// use scrollView's Content Layout Guide
let g = scrollView.contentLayoutGuide
// labelOne 16-pts from top
labelOne.topAnchor.constraint(equalTo: g.topAnchor, constant: 16.0).isActive = true
// labelOne 16-pts from leading
labelOne.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0).isActive = true
// labelOne 16-pts from trailing (so we can scroll 2000-pts
labelOne.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0).isActive = true
// if we want vertical scrolling of 2000-pts
// and labelOne to be 100-pts tall with 16-pts on top
// constrain labelOne bottom (2000 - (100 + 16)) from content guide bottom
labelOne.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -(2000.0 - (100.0 + 16.0))).isActive = true
}
}