9
votes

I've been looking for days for a (working) tutorial or even an example app that uses UIScrollView to scroll vertically, programatically that is. There's tons of tutorials on using storyboard, leaving me at a loss.

I looked through apple's documentation, and their "guide" still not having a solid example or hint as to where to start.What I've attempted so far, is doing some of the following.

Making my view a scrollview Directly in the class

let scrollView = UIScrollView(frame: UIScreen.mainScreen().bounds)

Then assigning it to the view in my viewDidLoad function

self.view = scollView

Attempting to change the content size.

self.scrollView.contentSize = CGSize(width:2000, height: 5678)

Trying to enable scrolling with

scrollView.scrollEnabled = true

And the last suggestion I could find on doing this programatically

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    scrollView.frame = view.bounds
}

Currently I havn't tried to start adding my objects to the scrollview, (I don't need to zoom, just do vertical scrolling), but I havn't managed to get anything working whatsoever :( In fact, running the app with those additions simply causes UIProblems, The screen is moved up weirdly, and it doesn't fit the entire width of my screen? I tried fixing that making the frame bounds equal to the width, but still didn't work

I'm not getting any errors.

I would love to see an example viewcontroller that you can scroll vertically in! Or any help would be hugely appreciated!

EDIT with screenshot of the disaster, attempting to make my view scrollable causes.

Screen Shot

(link instead of image, due to lack of points to directly put an image.)

(I made the scrollview background red, to see if it was even showing up correctly. Which it seems to be. Yet I can't scroll anywhere

As suggested in the comments, instead of doing self.view = self.scrollview, I tried adding scrollview as a subview of self.view instead, but with no positive results.

EDIT 2:

Adding

scrollView.contentSize = CGSize(width:2000, height: 5678)

to viewDidLayoutSubviews, as suggested in the comments below made my view scrollable!

However my layout still looks like a complete mess for some reason (it looks as it's supposed to, before I made it scrollable).

Here's an example constraint for my topBar (blue one), that's supposed to take up the entire horizontal space.

self.scrollView.addConstraints(
        NSLayoutConstraint.constraintsWithVisualFormat(
            "H:|[topBar]|", options: nil, metrics: nil, views: viewsDictionary))

Any ideas why this doesn't work?

2
Have you tried instead of replacing the current view, adding the scrollView as a subview? - tkanzakic
I will try that right away! - Mark L
Added it as a subview, and changed all my "self.view.addsubview(..) to self.scrollView.addSubView(...), same with my constraints. But it still looks awful. Let me update my post, with an image of the disaster. - Mark L
put self.scrollView.contentSize = CGSize(width:2000, height: 5678) in viewDidLayoutSubviews and let me know what happens... & in viewDidAppear too... - Fahim Parkar
I think problem is here self.view = scollView should be self.view.addSubview(scollView) not sure what will be swift syntax but add subview... - Fahim Parkar

2 Answers

13
votes

Strictly I feel problem is at below line.

self.view = scollView

It should be self.view.addSubview(scollView)

Then add all label, buttons, etc in scrollview and then give content size.

Content size is the parameter that will tell scrollview to scroll.

Put self.scrollView.contentSize = CGSize(width:2000, height: 5678) inside viewDidLayoutSubviews.

23
votes

Swift 4.2

I make simple and complete example of scroll a stack view using auto layout.

All view are in code and don't need story board.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(scrollView)
        scrollView.addSubview(scrollViewContainer)
        scrollViewContainer.addArrangedSubview(redView)
        scrollViewContainer.addArrangedSubview(blueView)
        scrollViewContainer.addArrangedSubview(greenView)

        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

        scrollViewContainer.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
        scrollViewContainer.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
        scrollViewContainer.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        scrollViewContainer.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
        // this is important for scrolling
        scrollViewContainer.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
    }

    let scrollView: UIScrollView = {
        let scrollView = UIScrollView()

        scrollView.translatesAutoresizingMaskIntoConstraints = false
        return scrollView
    }()

    let scrollViewContainer: UIStackView = {
        let view = UIStackView()

        view.axis = .vertical
        view.spacing = 10

        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    let redView: UIView = {
        let view = UIView()
        view.heightAnchor.constraint(equalToConstant: 500).isActive = true
        view.backgroundColor = .red
        return view
    }()

    let blueView: UIView = {
        let view = UIView()
        view.heightAnchor.constraint(equalToConstant: 200).isActive = true
        view.backgroundColor = .blue
        return view
    }()

    let greenView: UIView = {
        let view = UIView()
        view.heightAnchor.constraint(equalToConstant: 1200).isActive = true
        view.backgroundColor = .green
        return view
    }()
}

hope this help!