Search code examples
iosswiftuicollectionviewuikitscrollview

ScrollView with AutoLayout not working


I've struggling a lot with UIScrollView to add programmatically subviews, I've seen a lot of tutorials but they all focus on storyboards and don't really solve my issue I'm just trying to add a few subviews to a scrollView but don't get to show anything on the device, it only displays the scrollView without my subviews, im trying to do something like this:

view.addSubview(mainScrollView)

mainScrollView.anchor(top: view.safeAreaLayoutGuide.topAnchor, right: view.rightAnchor, bottom: view.bottomAnchor, left: view.leftAnchor, topPadding: 10, rightPadding: 0, bottomPadding: 0, leftPadding: 0, width: 0, height: 0)

let v1 = UIView()
v1.backgroundColor = .blue

let v2 = UIView()
v2.backgroundColor = .black

let v3 = UIView()
v3.backgroundColor = .yellow

let v4 = UIView()
v4.backgroundColor = .green


mainScrollView.addSubview(v1)
mainScrollView.addSubview(v2)
mainScrollView.addSubview(v3)
mainScrollView.addSubview(v4)


v1.anchor(top: mainScrollView.topAnchor, right: nil, bottom: nil, left: nil, topPadding: 0, rightPadding: 0, bottomPadding: 0, leftPadding: 0, width: mainScrollView.contentSize.width, height: 0)

v2.anchor(top: v1.bottomAnchor, right: nil, bottom: nil, left: nil, topPadding: 0, rightPadding: 0, bottomPadding: 0, leftPadding: 0, width: mainScrollView.contentSize.width, height: 0)

v3.anchor(top: v2.bottomAnchor, right: nil, bottom: nil, left: nil, topPadding: 0, rightPadding: 0, bottomPadding: 0, leftPadding: 0, width: mainScrollView.contentSize.width, height: 0)

v4.anchor(top: v3.bottomAnchor, right: nil, bottom: mainScrollView.bottomAnchor, left: nil, topPadding: 0, rightPadding: 0, bottomPadding: 0, leftPadding: 0, width: mainScrollView.contentSize.width, height: 0)

anchor is just a helper extension to make it easier to constrain and activate the constraints


Solution

  • 1- Any programmatically view with constraints should

    v.translateAutoresizingMaskIntoconstarints = false
    

    2- You don't give height constraints to v1...4 ,, check this

    import UIKit
    
    class ViewController: UIViewController {
    
        let scrollView = UIScrollView()
    
        override func viewDidLoad() {
    
            super.viewDidLoad()
    
            let viewsCount = 7
    
            var prevView = self.view!
    
            scrollView.translatesAutoresizingMaskIntoConstraints = false
    
            view.addSubview(scrollView)
    
              NSLayoutConstraint.activate([
    
                scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                scrollView.topAnchor.constraint(equalTo: view.topAnchor,constant:20),
                scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
    
             ])
    
            for i in 0..<viewsCount {
    
                let myView = UIView()
    
                myView.backgroundColor =  (i % 2 == 0 ) ? .red : .green
    
                myView.translatesAutoresizingMaskIntoConstraints = false
    
                scrollView.addSubview(myView)
    
                if prevView == self.view {
    
                    myView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
                }
                else {
    
                    myView.topAnchor.constraint(equalTo: prevView.bottomAnchor).isActive = true
                }
    
                NSLayoutConstraint.activate([
    
                    myView.widthAnchor.constraint(equalToConstant: self.view.frame.width),
                    myView.heightAnchor.constraint(equalToConstant: 400)
    
                ])
    
    
                if i == viewsCount - 1  {
    
                    myView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
                }
    
                prevView = myView
    
    
            } 
        }
    }