0

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

nsleche
  • 108
  • 1
  • 7

3 Answers3

2

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


        } 
    }
}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
0

Because you are initialising the subviews with no frame, it seems like your views have no height, unless the anchor function does something to give them height.

cs95
  • 379,657
  • 97
  • 704
  • 746
Aidan Malone
  • 400
  • 3
  • 7
0

this is the extension

extension UIView {
func anchor(top: NSLayoutYAxisAnchor?, right: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, left: NSLayoutXAxisAnchor?, topPadding: CGFloat, rightPadding: CGFloat, bottomPadding: CGFloat, leftPadding: CGFloat, width: CGFloat, height: CGFloat) {

    translatesAutoresizingMaskIntoConstraints = false

    if let top = top {
        self.topAnchor.constraint(equalTo: top, constant: topPadding).isActive = true
    }
    if let right = right {
        self.rightAnchor.constraint(equalTo: right, constant: -rightPadding).isActive = true
    }
    if let bottom = bottom {
        self.bottomAnchor.constraint(equalTo: bottom, constant: -bottomPadding).isActive = true
    }
    if let left = left {
        self.leftAnchor.constraint(equalTo: left, constant: leftPadding).isActive = true
    }

    if width != 0 {
        self.widthAnchor.constraint(equalToConstant: width).isActive = true
    }
    if height != 0 {
        self.heightAnchor.constraint(equalToConstant: height).isActive = true
    }

}

}
nsleche
  • 108
  • 1
  • 7