Adrian
Adrian

Reputation: 20058

Why is there a gap between horizontal scrollview content?

I have setup a UIScrollView which contains two ViewController's. This is how my viewDidLoad looks like:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    scrollView.delegate = self

    self.automaticallyAdjustsScrollViewInsets = false

    let allViewController = self.storyboard!.instantiateViewControllerWithIdentifier("All") as! AllViewController;
    let favoritesViewController = self.storyboard!.instantiateViewControllerWithIdentifier("Favorites") as! FavoritesViewController;

    scrollView!.contentSize = CGSizeMake(2*CGRectGetWidth(allViewController.view.frame), CGRectGetHeight(scrollView!.frame));

    let viewControllers = [allViewController, favoritesViewController]

    var idx:Int = 0;

    for viewController in viewControllers {
        addChildViewController(viewController);
        let originX:CGFloat = CGFloat(idx) * CGRectGetWidth(scrollView!.frame);
        viewController.view.frame = CGRectMake(originX, 0, viewController.view.frame.size.width, viewController.view.frame.size.height);
        scrollView!.addSubview(viewController.view)
        viewController.didMoveToParentViewController(self)
        idx++;
    } 

On the iPhone 6 simulator everything works ok, but when I run it on the iPhone 5 simulator there is gap between the controllers when scrolling:

[enter image description here] The scrollView has auto layout set as 0 for leading, trailing, top and bottom.

Upvotes: 4

Views: 1134

Answers (4)

Neil Galiaskarov
Neil Galiaskarov

Reputation: 5073

If you want to set the origins in viewDidLoad: and you definitely know that your scroll view will have the width of your screen, in your calculation logic instead of CGRectGetWidth(scrollView!.frame) use

var bounds = UIScreen.mainScreen().bounds
var width = bounds.size.width

in order to get proper width before your subviews did layout.

Code: Working Github Project

UPD: As someone mentioned here, I unchecked scrollview's Autoresize Subviews property, subclassed UITableViewCell and pushed my commit to github. Check it through the link I provided above. Here you are the results with button aligned to the right:

Results:

enter image description here enter image description here

Reference: The main concepts are described in my SO answer here

Upvotes: 2

Stefan
Stefan

Reputation: 1496

If your subviews should always be the size of the scroll view the simplest solution may be to add a custom subclass of UIScrollView that just layouts all subviews in the order they where added like so:

import UIKit

class MyScrollView: UIScrollView {

    override func layoutSubviews() {
        super.layoutSubviews()
        var idx:Int = 0;
        contentSize = CGSizeMake(2*CGRectGetWidth(bounds), CGRectGetHeight(bounds));
        for sview in self.subviews as! [UIView] {
            let originX:CGFloat = CGFloat(idx) * CGRectGetWidth(bounds);
            sview.frame = CGRectMake(originX, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds));
            idx++
        }
    }

}

You can then simplify viewDidLoad to

override func viewDidLoad() {
    super.viewDidLoad()

    self.automaticallyAdjustsScrollViewInsets = false

    let allViewController = self.storyboard!.instantiateViewControllerWithIdentifier("All") as! AllViewController;
    let favoritesViewController = self.storyboard!.instantiateViewControllerWithIdentifier("Favorites") as! FavoritesViewController;

    for viewController in [allViewController, favoritesViewController] {
        addChildViewController(viewController);
        scrollView!.addSubview(viewController.view)
        viewController.didMoveToParentViewController(self)
    }
}

Upvotes: 1

Andrei L
Andrei L

Reputation: 3641

Add two subviews in your scrollview as placeholders, and add constraints betwen them and scrollview, and make two @IBOutlet to placeholders.
In viewDidLoad just set scrollView size, add childViewControlers and their views add to placeholders

Upvotes: 0

Sean Kladek
Sean Kladek

Reputation: 4446

You're setting the view controller positions in view did load. At that point, the views will have the dimensions matching the size of the views from your storyboard. I'm assuming you're using 4.7" views in your storyboards. This means that in viewDidLoad, you're setting the second view controller's x position to 375. Set the view controller position in viewWillAppear or didLayoutSubviews to get the correct width of the view (320 on iPhone 5). Note, both of those methods can be called more than once so plan accordingly.

Upvotes: 1

Related Questions