I have a Scroll View nested inside a View Controller which is rested in a Container. The View Controller, which uses a specified class called ScrollingViewController
looks like this:
class ScrollingViewController: UIViewController {
@IBOutlet weak var scrollView: UIScrollView! //outlet for the Scroll View
override func viewDidLoad() {
super.viewDidLoad()
// 1) Create the two views used in the swipe container view
var storyboard = UIStoryboard(name: "App", bundle: nil)
var subOne: SubProfileOneViewController = storyboard.instantiateViewControllerWithIdentifier("subone") as! SubProfileOneViewController
var subTwo: SubProfileTwoViewController = storyboard.instantiateViewControllerWithIdentifier("subtwo") as! SubProfileTwoViewController
// 2) Add in each view to the container view hierarchy
// Add them in opposite order since the view hierarchy is a stack
self.addChildViewController(subTwo);
self.scrollView!.addSubview(subTwo.view);
subTwo.didMoveToParentViewController(self);
self.addChildViewController(subOne);
self.scrollView!.addSubview(subOne.view);
subOne.didMoveToParentViewController(self);
// 3) Set up the frames of the view controllers to align
// with each other inside the container view
var adminFrame :CGRect = subOne.view.frame;
adminFrame.origin.x = adminFrame.width;
subTwo.view.frame = adminFrame;
// 4) Finally set the size of the scroll view that contains the frames
var scrollWidth: CGFloat = 2 * self.view.frame.width
var scrollHeight: CGFloat = 262
self.scrollView!.contentSize = CGSizeMake(scrollWidth, scrollHeight);
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Basically what's happening is that two View Controllers that use that class SubProfileOneViewController
and SubProfileTwoViewController
, respectively, are being instantiated as subOne
and subTwo
. These are then added into the Scroll View as children in order to create an interface where the user can swipe right to access another view (almost like Snapchat). subOne
and subTwo
should be side by side and the user should be able to scroll from one to the next and vice versa.
Here's what this all looks like on my storyboard:
SubProfileOneViewController
and SubProfileTwoViewController
each have a view (represented by green and red respectively) and each have the same exact constraints which are: Height = 262, Trailing space to superview = 0, Leading space to superview = 0, Top space to superview = 0
Ideally, when run, there should be two views, one green and one red and the user should be able to swipe between each one. However, here's what actually happens:
The green and red views don't take up the entire screen width and instead are condensed into a small sliver on the left, and the majority of the View Controllers are white instead of their respective color. I've tried many things and I'm not sure what I'm doing wrong.
(credit for code in ScollingViewController
goes to lbrendanl on github, linked here: https://github.com/lbrendanl/SwiftSwipeView)
ScrollView with auto layout works differently either you can use only one subview by setting translatesAutoresizingMaskIntoConstraints = true
and setting contentSize explicitly. Or you set translatesAutoresizingMaskIntoConstraints = false
and let it find out constraint it self. Visit this link for more details
As you want both should take full screen then you need to add AutoLayoutConstraints, something like this
Note: I would recommend using an Autolayout
solution, which will automatically handle orientation changes, screen sizes, all with much less code and more robust solution than what I develop below.
With the current approach, using embedded UIViewControllers
, you must wait for these controllers to complete their respective initializations, which are in direct competition with your layout.
Note that you will need to recalculate positions + sizes upon orientation changes. Again, while this works, it is not a sound design since it calls for a lot of code, logic, and general functionalities you would get for free using NSLayoutConstraint
.
(tested, built, linked and ran):
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// 3) Set up the frames of the view controllers to align
// with each other inside the container view
var adminFrame = self.view.frame
subOne.view.frame = adminFrame
adminFrame.offset(dx: self.view.frame.width, dy: 0)
subTwo.view.frame = adminFrame;
// 4) Finally set the size of the scroll view that contains the frames
let scrollWidth = 2 * self.view.frame.width
self.scrollView!.contentSize = CGSizeMake(scrollWidth, self.view.frame.height)
}
Here is the scrolling (in action). Notice that I created views of class ViewLayoutAssistant.swift which allows you to visualize position + scale very conveniently.
You also do not need to tell the view its hierarchy has changed. This last bit of code should get you going:
@IBOutlet weak var scrollView: UIScrollView!
weak var subOne: SubProfileOneViewController!
weak var subTwo: SubProfileTwoViewController!
self.addChildViewController(subTwo);
self.scrollView!.addSubview(subTwo.view);
self.addChildViewController(subOne);
self.scrollView!.addSubview(subOne.view);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With