skip to Main Content

I’m having trouble getting my ContentView to show up inside my ScrollView and I don’t know what I’m doing wrong to make it not visible. In my screenshot down below, the purple view is my ScrollView which is showing perfectly, and as you will see in my code, my ContentView is red. I tried to change my properties to lazy var to see if that would work, but I’m still having the same issue. Am I doing something wrong in my programmatic UI for my ContentView not to show up, or am I missing something? Thank you!

Screenshot of Problem

enter image description here

FindEmployeeJobRequestController

// MARK: - Properties

lazy var jobInfoCardView: ShadowCardView = {
   let view = ShadowCardView()
   view.backgroundColor = .white
   view.addShadow()
   view.setHeight(height: 320)
   return view
}()
    
let scrollView: UIScrollView = {
   let sv = UIScrollView()
   sv.backgroundColor = .darkPurpleTint
   sv.isScrollEnabled = true
   return sv
}()
    
let contentView: UIView = {
   let view = UIView()
   view.backgroundColor = .red
   return view
}()

// MARK: - Helper Functions

fileprivate func configureUI() {

        view.addSubview(jobInfoCardView)
        jobInfoCardView.anchor(top: circularProgressView.bottomAnchor, left: view.leftAnchor, right: view.rightAnchor,
                               paddingTop: 52, paddingLeft: 24, paddingRight: 24)
        
        jobInfoCardView.addSubview(scrollView)
        scrollView.anchor(top: jobInfoCardView.topAnchor, left: jobInfoCardView.leftAnchor,
                          bottom: jobInfoCardView.bottomAnchor, right: jobInfoCardView.rightAnchor,
                          paddingTop: 4, paddingLeft: 4, paddingBottom: 4, paddingRight: 4)
        
        jobInfoCardView.addSubview(contentView)
        contentView.anchor(top: scrollView.contentLayoutGuide.topAnchor, left: scrollView.contentLayoutGuide.leftAnchor,
                           bottom: scrollView.contentLayoutGuide.bottomAnchor, right: scrollView.contentLayoutGuide.rightAnchor)
        contentView.anchor(left: scrollView.frameLayoutGuide.leftAnchor, right: scrollView.frameLayoutGuide.rightAnchor)

}

UPDATE

I tried to add my contentView to my scrollView‘s subview, but it’s still not showing. I even tried to add an UIStackView to my contentView to see if that could make it visible, but still not visible.

Updated Screenshot

enter image description here

Updated Code

fileprivate func configureUI() {

        scrollView.addSubview(contentView)
        contentView.anchor(top: scrollView.contentLayoutGuide.topAnchor, left: scrollView.contentLayoutGuide.leftAnchor,
                           bottom: scrollView.contentLayoutGuide.bottomAnchor, right: scrollView.contentLayoutGuide.rightAnchor)
        contentView.anchor(left: scrollView.frameLayoutGuide.leftAnchor, right: scrollView.frameLayoutGuide.rightAnchor)
        
        waitingOnEmployeeStack.axis = .vertical
        waitingOnEmployeeStack.distribution = .fillEqually
        waitingOnEmployeeStack.spacing = 4
        
        contentView.addSubview(waitingOnEmployeeStack)
        waitingOnEmployeeStack.centerX(inView: contentView)
        waitingOnEmployeeStack.anchor(top: contentView.topAnchor, paddingTop: 5)

}

3

Answers


  1. I think you wanted to add the contentView as a subView of the scrollView.

    fileprivate func configureUI() {
        
        view.addSubview(jobInfoCardView)
        jobInfoCardView.anchor(top: circularProgressView.bottomAnchor, left: view.leftAnchor, right: view.rightAnchor,
                               paddingTop: 52, paddingLeft: 24, paddingRight: 24)
        
        jobInfoCardView.addSubview(scrollView)
        scrollView.anchor(top: jobInfoCardView.topAnchor, left: jobInfoCardView.leftAnchor,
                          bottom: jobInfoCardView.bottomAnchor, right: jobInfoCardView.rightAnchor,
                          paddingTop: 4, paddingLeft: 4, paddingBottom: 4, paddingRight: 4)
        
        scrollView.addSubview(contentView)
        contentView.anchor(
            top: scrollView.contentLayoutGuide.topAnchor,
            left: scrollView.contentLayoutGuide.leftAnchor,
            bottom: scrollView.contentLayoutGuide.bottomAnchor,
            right: scrollView.contentLayoutGuide.rightAnchor
        )
        contentView.anchor(
            left: scrollView.frameLayoutGuide.leftAnchor,
            right: scrollView.frameLayoutGuide.rightAnchor
        )
        
    }
    
    Login or Signup to reply.
  2. I think you might want to add contentView as scrollView‘s subview and not jobInfoCardView‘s subview

    Login or Signup to reply.
  3. Couple notes…

    I strongly recommend using standard constraint syntax – at least while you’re learning. We don’t know if your .anchor(...) funcs are doing the right thing, and when you review your code it’s not entirely clear what might be happening. Once you’ve really gotten the hang of auto-layout, you may find it easier to use "helper funcs" (personally, I don’t).

    Also – use comments so both you and we know what your intent is.

    Take a look at this…

    You haven’t shown what ShadowCardView might be, so we’ll start with just a plain UIView subclass:

    class ShadowCardView: UIView {
    }
    

    And an example controller class:

    class ViewController: UIViewController {
        
        lazy var jobInfoCardView: ShadowCardView = {
            let view = ShadowCardView()
            view.backgroundColor = .white
            return view
        }()
        
        let scrollView: UIScrollView = {
            let sv = UIScrollView()
            sv.backgroundColor = .purple // .darkPurpleTint
            return sv
        }()
        
        let contentView: UIView = {
            let view = UIView()
            view.backgroundColor = .red
            return view
        }()
        
        let circularProgressView: UIView = {
            let view = UIView()
            view.backgroundColor = .green
            return view
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
            view.backgroundColor = UIColor(red: 0.2, green: 0.6, blue: 0.8, alpha: 1.0)
        
            // we'll be using auto-layout constraints for all views
            [jobInfoCardView, scrollView, contentView, circularProgressView].forEach { v in
                v.translatesAutoresizingMaskIntoConstraints = false
            }
            
            // add views
            view.addSubview(circularProgressView)
            view.addSubview(scrollView)
            
            scrollView.addSubview(contentView)
            
            contentView.addSubview(jobInfoCardView)
            
            // respect safe area
            let safeG = view.safeAreaLayoutGuide
            
            // to make things a little more readable
            let contentG = scrollView.contentLayoutGuide
            let frameG = scrollView.frameLayoutGuide
            
            NSLayoutConstraint.activate([
                
                // let's put the circularProgressView 20-points from the Top
                circularProgressView.topAnchor.constraint(equalTo: safeG.topAnchor, constant: 20.0),
                // 60-points on each side
                circularProgressView.leadingAnchor.constraint(equalTo: safeG.leadingAnchor, constant: 60.0),
                circularProgressView.trailingAnchor.constraint(equalTo: safeG.trailingAnchor, constant: -60.0),
                // and give it 1:1 ratio
                circularProgressView.heightAnchor.constraint(equalTo: circularProgressView.widthAnchor),
                
                // let's put the scrollView 20-points from the Bottom of the progress view
                scrollView.topAnchor.constraint(equalTo: circularProgressView.bottomAnchor, constant: 20.0),
                // 20-points on each side
                scrollView.leadingAnchor.constraint(equalTo: safeG.leadingAnchor, constant: 20.0),
                scrollView.trailingAnchor.constraint(equalTo: safeG.trailingAnchor, constant: -20.0),
                // and give it 1:1 ratio
                scrollView.heightAnchor.constraint(equalTo: scrollView.widthAnchor),
    
                // constrain all 4 sides of contentView to scrollView's Content Layout Guide
                //  and we'll use 12-points "padding" so we can see its frame inside the scrollView
                contentView.topAnchor.constraint(equalTo: contentG.topAnchor, constant: 12.0),
                contentView.leadingAnchor.constraint(equalTo: contentG.leadingAnchor, constant: 12.0),
                contentView.trailingAnchor.constraint(equalTo: contentG.trailingAnchor, constant: -12.0),
                contentView.bottomAnchor.constraint(equalTo: contentG.bottomAnchor, constant: -12.0),
                
                // set the Width of contentView to the Width of scrollView's Frame Layout Guide
                //  mius 24-points (12 on each side)
                contentView.widthAnchor.constraint(equalTo: frameG.widthAnchor, constant: -24.0),
                
                // constrain all 4 sides of jobInfoCardView to contentView
                jobInfoCardView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0.0),
                jobInfoCardView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0.0),
                jobInfoCardView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0.0),
                jobInfoCardView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0.0),
    
            ])
            
        }
        
    }
    

    When run, it will look like this (green view is your circularProgressView and purple view is the scroll view):

    enter image description here

    That’s pretty much what you are already getting. That’s because – at the moment – ShadowCardView has no content to control its size. So, it’s not even visible.

    Let’s change ShadowCardView to this:

    class ShadowCardView: UIView {
        let stackView: UIStackView = {
            let v = UIStackView()
            v.axis = .vertical
            v.spacing = 20
            return v
        }()
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        private func commonInit() {
            stackView.translatesAutoresizingMaskIntoConstraints = false
            addSubview(stackView)
            NSLayoutConstraint.activate([
                // constrain all 4 sides of stackView to self
                //  and we'll use 8-points "padding" so we can see its frame
                stackView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8.0),
                stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 8.0),
                stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -8.0),
                stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8.0),
            ])
            
            // give the stackView a border so we can see its frame
            stackView.layer.borderColor = UIColor.systemBlue.cgColor
            stackView.layer.borderWidth = 1
            
            // add some labels
            for i in 1...30 {
                let v = UILabel()
                v.text = "Label (i)"
                v.backgroundColor = .cyan
                stackView.addArrangedSubview(v)
            }
        }
    }
    

    We’ve added a vertical stack view with 30 labels (along with proper constraints), and the output is now:

    enter image description here

    and we can scroll:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search