2

So, I have looked through almost all of Stackoverflow's answers to this particular question and even looked through tutorials that supposedly teach you how to use a scroll view but It doesn't seem to apply for my project..

Here is what I know so far, in order for a Scroll View to properly work you first need to give it a content size. This determines the scrollable height etc.

I have provided some code to give you all a better idea of how I am adding said items into my scrollview. If there is something that I am doing wrong or if there is a better way to go about doing this please let me know, I am still fairly new to Swift and iOS development and in my mind it feels like I am doing it correctly.

The steps I am taking

  1. Create items that I want to display (Input fields, Imageviews etc..)
  2. Add said items to the view of the viewcontroller. (view.addsubview(etc..))
  3. Create a scrollView and set its constraints to be same as the screen / view
  4. Add our view with all the items in it into said scroll view
  5. Relax and everything should work out perfect?????

Here is my code, I know it might be lengthy but I think it might be needed so that the scope of my question is understood

class JobRegistrationController: UIViewController {

// ... Omitted for clarity
lazy var scrollView: UIScrollView = {
    let view = UIScrollView(frame: UIScreen.main.bounds)
    view.backgroundColor = .red
    view.contentSize = CGSize(width: self.view.bounds.width, height: self.view.bounds.height * 2)
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

//... Omitted for clarity

    let scrollContentView: UIView = {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

override func viewDidLoad() {
    super.viewDidLoad()

    // Need so that view controller is not behind nav controller
    self.edgesForExtendedLayout = []

    view.addSubview(scrollView)
    scrollView.addSubview(scrollContentView)
    scrollContentView.addSubview(jobTypeField)
    scrollContentView.addSubview(jobTypeDividerLine)

    // x, y, width and height constraints
    scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    scrollView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true

    // x, y, width and height constraints
    scrollContentView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    scrollContentView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    scrollContentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    scrollContentView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true

    // x, y, width and height constraints
    jobTypeField.leftAnchor.constraint(equalTo: scrollContentView.leftAnchor, constant: 20).isActive = true
    jobTypeField.topAnchor.constraint(equalTo: scrollContentView.topAnchor).isActive = true
    jobTypeField.rightAnchor.constraint(equalTo: scrollContentView.rightAnchor, constant: -8).isActive = true
    jobTypeField.heightAnchor.constraint(equalToConstant: 30).isActive = true

    // x, y, width and height constraints
    jobTypeDividerLine.leftAnchor.constraint(equalTo: scrollContentView.leftAnchor, constant: 20).isActive = true
    jobTypeDividerLine.topAnchor.constraint(equalTo: jobTypeField.bottomAnchor).isActive = true
    jobTypeDividerLine.rightAnchor.constraint(equalTo: scrollContentView.rightAnchor).isActive = true
    jobTypeDividerLine.heightAnchor.constraint(equalToConstant: 0.5).isActive = true

4 Answers 4

4

Use this method in your class

  override func viewDidLayoutSubviews()
  {
   scrollView.delegate = self
   scrollView.contentSize = CGSize(width:self.view.frame.size.width, height: 1000) // set height according you
  }
Sign up to request clarification or add additional context in comments.

3 Comments

Hi, thanks for the suggestion. When I scroll around in my view, i can see the scroll bar moving up and down but the contents of my view are not moving
I think your view is not add properly in scroll view. Add Content View inside scrollview.
Hi do you have any suggestions on how to do this? I have made an edit in my code adding the scroll content view but its doing the same thing
4

The problem is that you don't tell where the bottom of your content is. In other words you need some bottom constraints.

If you use...

scrollContentView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true

...you need also to add a constraint to bind at least one view to the bottom of your UIScrollView like:

scrollContentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

... and also bind the last view in the scrollContentView to its bottomAnchor.

jobTypeDividerLine.bottomAnchor.constraint(equalTo: scrollContentView.bottomAnchor).isActive = true

This will sure fix your issue. Because this way the whole constraint sequence is linked from top to bottom.

Bottom line, the UIScrollView is not that smart that it determines its own bottom in every possible way. It is a kind of lazy. If you don't tell him enough it wouldn't simply scroll, while it is clear that your content disappears behind the bottom of your UIScrollView container.

Comments

3
view.contentSize = CGSize(width: self.view.bounds.width, height: self.view.bounds.height * 2)

You should try to log the contentSize in your console after trying to access it. I am not sure if you are setting the correct contentSize here if the self.view.bounds has been calculated correctly when this gets called at that moment. Since it takes time for self.view frame and bounds to be calculated.

Try setting your contentSize after you have added the actual content to it based on the actual total content size.

EDIT:

Add a single UIView inside the scrollView, with the constraints set to top-bottom-leading-trailing, and add your subviews to it. Also, set the same constraints on the scrollView to the superView top-bottom-leading-trailing.

7 Comments

Hi, thanks for the suggestion. When I scroll around in my view, i can see the scroll bar moving up and down but the contents of my view are not moving
@EdwardLim That is another problem. The solution for it is to put all your subviews inside a single UIView, that you inturn add the single UIView as a subview inside the scrollView . Avoid having all the subviews inside the scrollView without having a single UIView "scrollContentView" for them all. Otherwise you will run into massive bugs as you described for example.
Hi could you please suggest how to do this properly? I have already tried adding a view into the scroll view, but it seems to be doing the exact same thing.
@EdwardLim I really never add any constraints by code, I found it really messy when it is so easy to do in AutoLayout, so I might not be able to help you doing it by code. But what you need is basically an UIView as subview inside your scrollView. The UIView should have bottom-top-trailing-leading as 0 to your scrollview. And inside this UIView, you add all your subviews. That's it. To see where the error lies, log the contentSize and the subview size and see if the subview is less than contentsize. also
@EdwardLim remember to call layoutIfNeeded on your subviews that you are changing the the constraints on when changing the constraints constants if you do that.
|
1

I believe the line of code below is the problem

scrollContentView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true

You are setting your content view to the top of the view, when you should be setting it to the top of the scrollview.

I've just overcome a similar issue were I was setting the topAnchor of my first view to the safeAreaLayoutGuide.topAnchorof the scrollView. Everything laid out correctly but the constraint wouldn't show and therefore the entire content of the scrollView didn't move.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.