I have been messing with this code for a while. My UIViews are not showing up after looping through. I have tried this with out constraints, and the result was each of the UIViews were being rendered on top of each other. I would prefer to use the constraints, like I have it set up.
Can you take a look at this code and explain why my UIViews are not rendering and why my UIScrollViews are not scrolling?
import UIKit
class EventsListViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scrollView = UIScrollView()
let scrollViewConstraints: [NSLayoutConstraint] = [
scrollView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
scrollView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor)
]
self.view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(scrollViewConstraints)
scrollView.backgroundColor = .gray
let stackView = UIStackView(frame: scrollView.frame)
let stackViewConstraints: [NSLayoutConstraint] = [
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor),
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor)
]
scrollView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(stackViewConstraints)
stackView.axis = .vertical
stackView.distribution = .fill
stackView.alignment = .fill
stackView.contentMode = .top
stackView.spacing = 5
for event in location.myEvents! {
let listItem = UIView()
listItem.layer.name = event.eventID
listItem.backgroundColor = .blue
stackView.addArrangedSubview(listItem)
let listItemConstraints: [NSLayoutConstraint] = [
listItem.heightAnchor.constraint(equalToConstant: 35),
listItem.widthAnchor.constraint(equalToConstant: stackView.frame.width)
]
listItem.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(listItemConstraints)
}
// scrollView.contentSize = CGSize(width: Int(view.frame.width), height: (height + spacing * count))
}
}
I have tried the following:
- Without constraints results - all UIViews on top of each other
- With constraints results - UIViews not rendering
The big issue I see is that you constrain the stack view to the exact size of the scroll view.
UIScrollViewhas aframeLayoutGuideand acontentLayoutGuide. The stack view should be constrained to thecontentLayoutGuide. This will allow the stack view to be sized properly based on the views you put in it and it sets thecontentSizeof the scroll view as needed. And it will also allow the stack view to scroll within the scroll view if large enough.Here is a cleaned up version of your code with a bunch of comments. For testing purposes I simply hardcoded the creation of 20 views since I don't have your data model.
Note the change in
distributionfor the stack view. UsingequalSpacingallows each view to have its own height. The height of the stack view will be made as tall as need to account for the total height of all view and the spacing. Usingfill(as you had it) attempts to resize the height of the views to fill the height of the stack view. But you want the views to dictate the height of the stack view, not the other way around.Note that I remove the width constraint on each view. The stack view will take care of the width due to the
alignmentoffill.Also note the use of the
frameLayoutGuideandcontentLayoutGuide.Lastly, the last constraint sets the width of the stack view. This is needed since the views in the stack view do not give the stack view an intrinsic width in this case.