sudo make install
sudo make install

Reputation: 5669

UIScrollView behaves differently when embedded in a navigation controller

In this view controller, I initialize a UIScrollView, add it to the hierarchy and add autolayout constraints in viewDidLoad, and add an image subview in viewDidLayoutSubviews. If I assign this to a free-standing view in Storyboard, it behaves as expected (square scroll view with an image, I can scroll around). However, if I embed this view in a navigation controller, making no other changes, I instead get a black screen that fills the window, sans image.

Why is this happening, and how can I fix it? I've seen other questions [1] [2] that suggest setting the content size. However, I'm trying to use autolayout rather than setting the content size directly.

Here is a minimal but complete example. Again: works with freestanding view, not when embedded:

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

    var scrollView: UIScrollView = UIScrollView(frame: CGRectZero)

    override func viewDidLoad() {
        super.viewDidLoad()

        self.scrollView.delegate = self
        self.scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
        self.view.addSubview(self.scrollView)
        self.scrollView.maximumZoomScale = 2
        self.scrollView.minimumZoomScale = 1

        self.view.setTranslatesAutoresizingMaskIntoConstraints(false)

        self.configureAutolayout()
    }

    override func viewDidLayoutSubviews() {
        if let x = UIImage(named: "photo.jpg") {
            let y = UIImageView(image: x)
            self.scrollView.addSubview(y)
        }
    }

    func configureAutolayout() {

        var constraint = NSLayoutConstraint(item: self.scrollView,
            attribute: .Leading,
            relatedBy: .Equal,
            toItem: self.view,
            attribute: .Leading,
            multiplier: 1,
            constant: 0)
        self.view.addConstraint(constraint)

        constraint = NSLayoutConstraint(item: self.scrollView,
            attribute: .Trailing,
            relatedBy: .Equal,
            toItem: self.view,
            attribute: .Trailing,
            multiplier: 1,
            constant: 0)
        self.view.addConstraint(constraint)

        constraint = NSLayoutConstraint(item: self.scrollView,
            attribute: .Top,
            relatedBy: .Equal,
            toItem: self.topLayoutGuide,
            attribute: .Bottom,
            multiplier: 1,
            constant: 0)
        self.view.addConstraint(constraint)

        constraint = NSLayoutConstraint(item: self.scrollView,
            attribute: .Height,
            relatedBy: .Equal,
            toItem: self.scrollView,
            attribute: .Width,
            multiplier: 1,
            constant: 0)
        self.view.addConstraint(constraint)

    }

    func viewForZoomingInScrollView(scrollView: UIScrollView!) -> UIView! {
        return self.scrollView.subviews.first as UIView
    }

}

EDIT:

Removing the following line fixes one problem and introduces another:

self.view.setTranslatesAutoresizingMaskIntoConstraints(false)

The UIScrollView, with the image subview, now appear both in the independent view and when embedded in the navigation controller. However, there is now an extra, unwanted space at the top of the scrollview of the embedded controller. I thought that TopLayoutGuide was the appropriate view for alignment--is this not the case?

EDIT 2:

The inset problem was fixed by setting self.automaticallyAdjustsScrollViewInsets to false, as per this question [3]. It is not behaving as intended.

References:

[1] UIScrollView not scrolling when included into viewcontroller embedded into a navigation controller

[2] UIScrollView scroll not working after pushed with a navigation controller

[3] Explaining difference between automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout in iOS7

Upvotes: 4

Views: 4127

Answers (2)

Amit Kumar
Amit Kumar

Reputation: 603

In iOS10 It works for me. I'm Building a project in which I want to add scroll view in Navigation Controller

  1. First Add ScrollView in navigation controller's view.
  2. Then add constraint from pin on scrollview as (0 from top, 0 from left, 0 from right, 0 from bottom).
  3. Then another Uiview in Scrollview (structure mentioned in below picture). Structure of the scrollview and uiview..

  4. Then add contraint on view under scrollView as ("Equal Width, Equal Height, Center vertically in container, center horizontally in container)as given below..Adding constraint on view relative to scrollview How Do Add constraints

  5. Plus also add some constraints from pin from bottom and right(200 and 0 respectively). As In picture..Constraints from Pin.

  6. Then add anything what you want to add and add constraint on it from menu.

  7. click on your viewcontroller in main.Storyboard then make an @IBOutlet for your scrollview in your viewController.

  8. Then add these lines to your viewDidload() as scrollView(In my case)

    let testing : CGFloat = 1000  
    scrollView.contentSize.height = testing
    

Hope this works for you..!!!

Upvotes: 1

sudo make install
sudo make install

Reputation: 5669

As per the above two edits, the problem was solved by removing this line...

self.view.setTranslatesAutoresizingMaskIntoConstraints(false)

...and adding this one:

self.automaticallyAdjustsScrollViewInsets = false

Upvotes: 3

Related Questions