how to get auto layout to work in Xcode - ios

I looked into http://developer.apple.com/library/ios/#recipes/xcode_help-interface_builder/articles/UnderstandingAutolayout.html but the explanations are pretty vague.
I'm on iOS 6. I have a view controller with two child views, one on top of another:
I want to use autolayout to set up the views in such way that if I change the top view's frame programatically, the bottom view will resize to accommodate the top view's new frame. That is, if I increase the top view's height, the bottom view's height should drecrease to keep the same separation between both views; the opposite should happen if I decrease the top view's height.
The default constraints I get for these two views in Xcode are:
And if I hold Command and resize the top (map) view, the bottom (tableview) seems to correctly shrink or expand vertically to honor the space constraint between them.
However, the minute I try modifying the top view's frame or bounds via code, for instance:
self.topView.frame = CGRectMake(0, 0, 320, 514);
The bottom view doesn't shrink.
So what am I missing?

You can't modify self.topView.frame like that. Setting the frame is auto layout's job. You need to modify the constraints and then let auto layout update the frame.
Create an outlet of type NSLayoutConstraint in your view controller:
#property (nonatomic, strong) IBOutlet NSLayoutConstraint *topViewHeightConstraint;
Connect the outlet to the height=127 constraint on the top view in your storyboard. See this answer if you need more help connecting an outlet to the constraint.
Then, to change the height of the top view, and have auto layout update the frame of the bottom view too, set the constraint's constant:
self.topViewHeightConstraint.constant = 514;
At the end of the run loop (not right away, but before the screen is updated), auto layout will modify the frames of both views to satisfy the changed constraint.

Related

Not able to set ContainSize of my ScrollView through Storyboard

I am adding more than 8-9 controls in my ScrollView but I am not able to set ContaintSize of that ScrollView so that I can able to scroll and view all controlls.
I HAVE SET below constrains to my scrollview and add some controls into my scroll view with the help of contain view.
Scrollview.top respect to his superview
Scrollview.bottom respect to his superview
Scrollview.leading respect to his superview
Scrollview.trailling reapect to his superview
Than I have added UIView as contain view and set all constrain respect to scrollview.
Than added all controls into view but still its not scrolling as expected.
By below code I am able to set containview but its ststic one and cant assume that 1000 is my contanent height.
Scrollview.contentsize = CGSizeMake (Scrollview.frame.size.width,1000);
Above part is static as I have many lable with multiple line in it.
All data is dynamic comes from server si cant set it static.
Can any one help me out how to set autolayout of scrollview so I can get dynamic content size?
Edit: some time I am getting autolayout error into storyboard like below.
Scrollview has ambiguous scrollable content height
An while i reslove conflicts its not showing proper scrollview in my screen.
Faced the same issue recently. I'm sure that you did your research but here is the guide I used, nonetheless.
https://www.natashatherobot.com/ios-autolayout-scrollview/
Also if you have many labels it would be good consider using a 'UITableView' or a 'UIStackView'.
Edit
Make sure you center the scroll view vertically and horizontally in respect to its container.
You have to define constraints for the scroll view like this..
ScrollView :
top ,left , bottom, right pinned to superview.
ContainerView:
top, left , bottom , right pinned to scroll view
width pinned to main view
And make sure that every subview inside the container view should have constraints in such a way that it should define the height of container view.
As i understand your issue you forgot to set the height constraint of your contentView, just try by setting it.
No need to set the fix height of scrollView's contentSize, please see the below code.
self.scrollview.contentSize = CGSizeMake(self.contentView.frame.size.width, contentView.frame.origin.y + contentView.frame.size.height + 10);
Note: you need to add height and width constraint of contentView if you need scroll according to it.

iOS Scroll View doesn't scroll with auto layout with views added in programmatically

I have a ViewController with a scrollView and a content View inside.
Some labels and stuff inside the Content View as well.
Now after that, when the view load i have to pass in data from other places to this view controller, and then load some other views by code.
The scrollview Content height and height did get updated, and i did place the loading and adding of the views at ViewWillAppear. But even if the content size is bigger than the height of the scrollview, i just can't scroll it.
Scroll View Height:667. Scroll View Content Height :1632
ContentView Height :1632
Your scrollview did not scrolled because you gave fixed size to content view.
Don't worry, just make the outlet of height constraint.
Check below image , how to crete outlet of constrain,
Note :- You need to create out let of Height Constrain.
From your image.
And now set in your viewDidLayoutSubviews
-(void)viewDidLayoutSubviews
{
NSInteger screenheight=[ [ UIScreen mainScreen ] bounds ].size.height;
if (screenheight > 504 + 64)
{
_contentviewHeight.constant = screenheight-64;
}
}
And last but not the least , Don't forget to remove Tick from Adjust Scrollview insects,
In case of Autolayout, whatever view you are adding to scrollview. You have to add constraint (basically top constraint) so that Scrollview would calculate contentsize automatically.
refer below to add constraints programatically.
iOS create NSLayoutConstraint programmatically for table view cell content
Edit :-
Like you said SView is in storyboard. So create the constraint from storyboard itself on SView.
And E,R and H View will be added constraint programatically
And the link is just an example
You will use [self addConstraint] instead of [self.ContentView addConstraint]
Moreover refer this one too :-
iOS Autolayout Vertically equal space to fill parent view
OKAY, Finally.
After trying and retrying and to no avail.
I just gave up on putting auto layout on the ViewController which have the scroll view itself.
So I untick the auto layout, and then VOILA.
Apparently, the view controller which have the scroll view don't need autolayout. Just the views that i put in via code need auto layout in their storyboard. After i adjust all the constraints in the view properly and never giving them aspect ratio constraints but just fixed their width and height. Done.
So I hope anybody who have the same frustration as me see this and heed my advice. Don't bother putting auto layout on the scroll view or its content View. Just Untick it altogether. Do the autolayout for the views you want to put in. You just have to specify the views' width and height properly and it will work.

UIScrollView content size fixed to 600x600(Main.storyboard size)

I've been facing this issue from past 2 weeks and not yet got a solution.
I'm using UIScrollview in my application where the problem exists.
Generally in my app, there is dynamic text and images with different sizes will come from webservices. For example, imagine the Facebook Newsfeed. My application is similar to the Facebook newsfeed. Sometimes, there will be only text, sometimes there will be text and images. And comments for that post.
As i've seen in many links, the heirrarchy i'm following is SuperView-->UIScrollView-->Content View and the elements are placed in that content view. I'm assigning the constraints from the elements in the contentview to the Superview (ContentView --- constraints -- SuperView). When the content in the view exceeds the size of the superview, it has to scroll. But the scrollview content size is limited to the size of 600x600 i.e., in main.storyboard, when we design for W any x H any size. I've seen many tutorials and searched many sites. But following them gives me no luck.
Any help is appreciable.
Here is how to set up a scrollView in Interface Builder from scratch that works with Auto Layout.
Start with a new ViewController. Drag out a scrollView such that it fills the view. Untick Constrain to margins and constrain the left, top, right, and bottom edges of this scrollView to the left, top, right, and bottom of its superview with offsets of 0. This allows the scollView to fill the screen on any device in any orientation. You can make your scrollView take up less of the screen if you like, just make sure it is fully contrained.
Add a view to your scrollView. This should be the only top level view on your scrollView and it will serve as your contentView.
Constrain the left, top, right, and bottom edges of this contentView to the left, top, right, and bottom of the scrollView with offsets of 0. At this point, you will see warnings about ambiguous content size. That is because you haven't told it yet how big your content view will be.
To size the contentView, add width and height constraints to the contentView. If you want it to scroll, the width and height must be larger than the width and height of the scrollView itself. If you only want to scroll vertically, set the width of the contentView to be equal to the width of the scrollView. To do this, in the Document Outline view, control-drag from the contentView to the scrollView and select Equal Widths from the pop up.
If you want to be able to change the height of your contentView from code (to account for dynamic content), first create a height constraint for your contentView by control-dragging within the contentView and selecting Height from the pop up. Create an IBOutlet to the height constraint by control-dragging from the height constraint (found in the Document Outline view) to your ViewController's code. Give the outlet a name like scrollViewHeight then set the height with a value like scrollViewHeight.constant = 2000 when you need to change the scrollView's height.
Simply add your UIScrollView to your UIViewController's view in the storyboard and add the appropriate constraints in the interface builder.
Then, build your content view in the code and give it any frame you want, now start adding your controls to this content view and calculate the size of each one (especially the height), and at the end you have the total height of your controls.
Now set the frame of the content view to match that height and add it as a sub view to your scroll view, then set the content size in the code like this:
_scrollView.contentSize = contentView.frame.size;
Another note, do this changes to the sizes in the viewDidLayoutSubviews to avoid any problems with different screen sizes but be careful, this event is called many times so have a BOOL or something to ensure that the code that creates the view and add it to the scroll view is executed once, e.g. like this
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (! built) {
// Do everything I explained above here
built = YES;
[self.view layoutSubviews];
}
}

UIScrollView Not Scrolling in iPAD

I have a UiViewController, inside which I have a UIScrollView with the width and height as 768X3000. Inside the UIScrollView I have a view with widht and height as 768X1024.
I am totally confused on how to implement UIScrollView. My scrollView doesnt work. I have lot of contents to be displayed in the UIView and UIScroll doesnt scroll down.
What connections or setting do I have to do make the UIScrollView work.
You need to set the contentSize property of your UIScrollView to 768 x 3000, not its frame or its bounds. So in viewWillAppear you could add code to set your scrollView's contentSize:
self.scrollView.contentSize = CGSizeMake(768.0f, 3000.0f);
1- viewDidLoad is to soon. You must wait until after the layout of the views has taken place. Try setting the contentSize in viewDidAppear.
-(void)viewDidAppear:(BOOL)animated{
myScrollView.contentSize = CGSizeMake(768, 3000);
}
2- another tip you can set contentSize in viewDidLayoutSubviews:
3- set the delegate of your scrollview
myScrollView.delegate=self;
//in case you need the delegate methods
4- If still you cannot scroll the view even after you set contentSize correctly, make sure you uncheck "Use AutoLayout" in Interface Builder -> File Inspector. Reference
If you're using storyboards in Xcode 5 and developing for Auto Layout then there are a few constraints you need for it all to work (in my experience). First, lay your views out like this:
main view
scroll view
content view (put all the stuff you want to scroll in this view)
Then do the following in this order in the storyboard editor:
Set the content view height to 3000. Width should be 768.
Set the scroll view height to 1024. Width should be 768.
Set the main view height to 1024 if in freeform sizing or leave it using inferred sizing. Width should be 768.
Before you do the next steps, just double-check each view's height to be sure nothing changed. Sometimes the storyboard editor makes bizarre changes on its own.
Set a height constraint for the content view only. It should be set at 3000.
Pin the top, bottom, right, and left sides of the content view to the scroll view using 0 for each edge. You will have to manually change the bottom constraint from a negative number to 0. This is very important, so I'll repeat it: manually change the bottom constraint to 0.
Pin the top, bottom, right, and left sides of the scroll view to the main view using 0 for each edge.
Now it should scroll. If you want to ensure that it stays centered when you change to a horizontal orientation, add a horizontal center constraint to the content view as well.
I have many scrolling views in my iPad app and didn't have to use the .contentSize code once if I built my views this way in the storyboard editor.
Good luck! I know what an absolute pain and time-waster this can be.

How can I use Autolayout to set constraints on my UIScrollview?

I have spent two days trying out the various solutions for Mixed and Pure Autolayout approaches to achieve what was a trivial scrollview setup prior to autolayout, and it's now official - I must be too stupid. I am setting this up mostly in Storyboard (well, it's just the way it is).
So here's my plea for help.
Viewtree:
UIView
-UIView
-UIView
..-UIScrollview
...-UIButton
...-UIButton
...-UIButton
The buttons are supposed to scroll horizontally (left to right and vice versa). Can someone please let me know how to set the constraints to achieve this using pure Autolayout???
--
I have tried the mixed approach, like so:
UIView
- UIView
- UIView
..-UIScrollview
...-UIView (contentview)
....-UIButton
....-UIButton
....-UIButton
...and setting fixed width and height constraints for the contentview and the translatesAutoresizingMaskIntoConstraints settings as per Apple's TechNote. The buttons and scrollview are set up using constraints. This gets the scrollview scrolling (yay) but alas, it scrolls too far! As far as I can tell, the scroll width is somehow doubled from what I set the contentview at???!!!???
I tried the pure autolayout approach as well, both with contentview and without. All the views are translatesAutoresizingMaskIntoConstraints=NO, except for self.view. The buttons have fixed width/height constraints, and are pinned to all four edges of the scrollview. Nothing scrolls.
So I am totally baffled why I can't get it to work correctly. Any help is much appreciated, and if you need any other info, please ask!
UPDATED Screenshot with solution -
buttonZ constraints:
EDIT # Jamie Forrest
So the solution turns out to be the wrong trailing constraint on the last button. Instead of 6441, the value I had set was negative, -6441. The tricky thing is, that when setting the value in storyboard, there are two options in the Pin toolbar:
The Current Canvas Value is negative (leading to no scroll), and the option below is positive (activating scroll). This means I'm not stupid but at least half-blind I guess. Although, to my defense, isn't it somewhat disturbing that XCode doesn't show an error for the "incorrect" setting?
EDITED AGAIN
Now this is funny... changing the trailing value from -6441 (no scroll) to 6441 enabled scroll. But my old friend the "too much contentsize" was back, leading to a content size twice as large as what it should be! The solution to get the correct content scroll was to set the trailing constraint to ZERO! This is not obvious when working in Storyboard but looking at #Infinity James' code, it is what it should be.
It's hard to see the exact values and setup of your constraints as you've pasted them here, so I'm not sure from looking at your screenshots where you have gone wrong.
In lieu of an explanation of what's wrong in your setup, I've created a basic sample project with a very similar view hierarchy and constraint setup to the one you describe. The horizontal scrolling works as expected in the sample project, which uses the "Pure AutoLayout" approach that Apple describes in the Technical Note.
I also had a lot of trouble originally getting Auto Layout to work with UIScrollView. The key to getting it to work is making sure that all of the items in the scroll view, taken together, have constraints that eventually link to all sides of the scroll view and that contribute to the AutoLayout system being able to determine a contentSize for the scroll view that will be bigger than its frame. It looks like you were trying to do that in your code, but maybe you had some superfluous constraints in there that were making the contentSize too small.
Also of note, as others mentioned, with AutoLayout and UIScrollview, you no longer set the contentSize explicitly. The AutoLayout System calculates the contentSize based on your constraints.
I also found this ebook chapter to be very helpful in making me understand how all this works. Hope all this helps.
LOL welcome to the stupidity club. I'm one of the founders. :D
For VERTICAL scrolling: the only way I could get it to work (iOS 8, Xcode 6 and pure autolayout) was adding the following constraints to my Scroll View (all related to the superview):
Equal Widths
Equal Heights
Center Y Alignment
Center X Alignment
My structure:
UIView
- ScrollView
- Subview
- Subview
- Subview
- Subview
- ...
This is the final result:
This is the setup:
Full screen
And here is the project.
Hopefully this would save someone from GOING TO SLEEP AT 5 AM. :D
Simple Self-Contained Example
Judging by the high number of votes on the question and the low number of votes on the answers, people are not finding an understandable and quick solution here. Let me try to add one. This project is a self-contained example done completely in the Interface Builder. You should be able to work through it in 10 minutes or less. Then you can apply the concepts you learned to your own project.
The original question asks about scrolling buttons. Here I just use UIViews but they can represent whatever view you like. I also chose horizontal scrolling because the storyboard screenshots are more compact for this format. The principles are the same for vertical scrolling, though.
Key concepts
The UIScrollView should only use one subview. This is a 'UIView' that serves as content view to hold everything you wish to scroll.
Make the content view and the scroll view's parent have equal heights for horizontal scrolling. (Equal widths for vertical scrolling)
Make sure that all of the scrollable content has a set width and is pinned on all sides.
Start a new project
It can be just a single view application.
Storyboard
In this example we will make a horizontal scroll view. Select the View Controller and then choose Freeform in the Size Inspector. Make the width 1,000 and the height 300. This just gives us room on the storyboard to add content that will scroll.
Add a Scroll View
Add a UIScrollView and pin all four sides to the root view of the view controller.
Add a Content View
Add a UIView as a subview to the scroll view. This is key. Don't try to add lots of subviews to the scroll view. Just add a single UIView. This will be your content view for the other views you want to scroll. Pin the content view to the scroll view on all four sides.
Equal Heights
Now in the Document Outline, Command click both the content view and the scroll view's parent view in order to select them both. Then set the heights to be equal (Control drag from the Content View to the Scroll View). This is also key. Because we are scrolling horizontally, the scroll view's content view won't know how high it should be unless we set it in this way.
Note:
If we were making the content scroll vertically, then we would set the content view's width to be equal to the scroll view's parent's width.
Add content
Add three UIViews and give them all constraints. I used 8 point margins for everything.
Constraints:
Green view: pin the top, left, and bottom edges. Make the width 400.
Red view: pin the top, left, and bottom edges. Make the width 300.
Purple view: pin all four edges edges. Make the width whatever the remaining space is (268 in this case).
Setting the width constraints is also key so that the scroll view knows how wide its content view will be.
Finished
That's all. You can run your project now. It should behave like the scrolling image at the top of this answer.
For vertical scrolling, just swap all the width and height directions in this example (tested and working).
Further Study
iOS: How To Make AutoLayout Work On A ScrollView
How to configure a UIScrollView with Auto Layout in Interface Builder
YouTube video tutorial: UIScrollView - How to keep your views on screen
The contentSize is implicitly set by applying the constraints inside of the UIScrollView.
For example, is you have a UIScrollView inside of a UIView it will look like this (as I am sure you are aware):
UIView *containerView = [[UIView alloc] init];
UIScrollView *scrollView = [[UIScrollView alloc] init];
[containerView addSubview:scrollView];
containerView.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(containerView, scrollView);
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[scrollView]|"
options:kNilOptions
metrics:nil
views:viewsDictionary]];
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[scrollView]|"
options:kNilOptions
metrics:nil
That will set the scrollView to fill the size of the containerView (so the containerView will have to be of a certain size).
You can then adjust the contentSize of the UIScrollView by implicitly setting it to be large enough to hold the buttons like this:
UIButton *buttonA = [[UIButton alloc] init];
UIButton *buttonB = [[UIButton alloc] init];
UIButton *buttonC = [[UIButton alloc] init];
[scrollView addSubview:buttonA];
[scrollView addSubview:buttonB];
[scrollView addSubview:buttonC];
buttonA.translatesAutoresizingMaskIntoConstraints = NO;
buttonB.translatesAutoresizingMaskIntoConstraints = NO;
buttonC.translatesAutoresizingMaskIntoConstraints = NO;
viewsDictionary = NSDictionaryOfVariableBindings(scrollView, buttonA, buttonB, buttonC);
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[buttonA]-|"
options:kNilOptions
metrics:nil
views:viewsDictionary]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[buttonA]-[buttonB]-[buttonC]-|"
options:NSLayoutFormatAlignAllBaseline
metrics:nil
views:viewsDictionary]];
There are so many questions about using AutoLayout with UIScrollView, the key point which we ignore is that the inner views of the UIScrollView make constraints against the Content View but not the UIScrollView itself. Refer to the Technical Note TN2154, you can find:
The UIScrollView class scrolls its content by changing the origin of its bounds. To make this work with Auto Layout, the top, left, bottom, and right edges within a scroll view now mean the edges of its content view.
The following figure will depicts that:
You can find the trailing space is 500 points, if the constraint is made to the UIScrollView, the view will be miss placed and should be update its frame. However, no warnings and no errors. Because all the constraints are against the content view.
UIScrollView will calculate the size of the content view according to the constraints of the inner views. (For the example, the content size: width = 100(leading space) + 200 (view's width) + 500 (trailing space), height = 131 (top spacing) + 200(height) + 269(bottom spacing)
How to add constraints for views in the UIScrollView:
Imaging the positions of views in the content view.
Add top, right, bottom, left spacing to the edges of the content view, in addition, also the width and height of these views.
And all it is done.
An easy way to deal with AutoLayout with scrollview is to add a container view containing all subviews in the scroll view.
Conclusion: the key point to understand AutoLayout with UIScrollView is inner views make constraints against the content view but not UIScrollView itself.
attached example code
The following solution worked for me for scrollView with autolayout and without contentSize:
Drag n drop a scrollView to viewController and apply whatever constraints to cover the space you want.
Drag n drop a UIView inside the scrollView and make it cover the whole space of scrollView and apply constraints to be top, left, right, bottom space from scrollView.
Set the height (and width if horizontal scrolling is required) of the inner view as per the need of scrolling. This part can also be done from code if required.
Critical. After you set the height to some large value in point (3), go back to point (2) and be certain to set the top, left, right, bottom values back to zero as Xcode may have changed them for you when you force changed the height in (3).
And you're done. Now, you can add any number of controls on this view and apply the constraints relevant to each other (which don't seem working without this view). If you don't want to use this view then you'll have to apply constraints for each control related to scrollView (not related to each other).
The overwhelming tip..............
Critical. Let's say for clarity the UIScrollView is 1000 wide and 100 high. (In fact normally these values would be dynamic, of course, depending on the width of the device etc. But for now just say 1000 wide and 100 high.) Let's say you are doing a horizontal scroll. So put a UIView inside the UIScrollView. (That is the "content view".) Set all four constraints of the content view top, bottom, leading, trailing, to the scroll view. Make them all zero even if that seems wrong. Set the height of the content UIView to 100 and forget about that. Now: you want to scroll horizontally, so set the width of the content view to be let's say 1225.
Note that the width of the content view is now 225 bigger than the width of the parent scroll view. That's OK: in fact, you MUST do that. Note that
...you do NOT set the trailing width to negative 225...
you would think you have to "match" the widths as you normally would. But if you do that, it will not work at all.
You must set the leading and trailing numbers to ZERO, never negative (even though the width is "bigger")
Interestingly, you can actually set the leading/trailing numbers to any positive value (try say "50") and it gives you kind of a margin of the bounce. (It often looks great: try it.) Any negative value on either end will "silently break".
Note that, infuriatingly, often Xcode (as of 7.3.1 anyway),
will 'helpfully' set those values for you to negative numbers!
because it tries to automatically tally them for you. If so it will silently break. Set all four values to zero in the first instance. And set the width of the content view much wider than the "1000" in the example.
Edited:
I've ended up with using UITableView instead of UIScrollView for most of my requirement. As tableView seems to me much more flexible and dynamic.
I assume you are running into issues with thecontentSize. Check out this blog post on how to handle the contentSize when using a "pure" AutoLayout approach. The gist of it is that your constraints implicitly define the content size. You NEVER set it explicitly when using AutoLayout. I've attached example project at the end of the blog post to demonstrate how it works
There is a piece in the tech notes that you may have looked over. You can implicitly set the content size of a scroll view using constraints fixed to the edges of the scroll view.
Here's a simple example. Create a storyboard with one view, that has one scroll view. Set that scroll views constraints to make it fit the size of the view you put it in.
Inside that scroll view add a single view. Explicitly set the size of that view using constraints (and make sure that size is bigger than the scroll view).
Now add four more constraints to that inner view locking the four edges of the inner view to its parent scroll view. Those four constraints will cause the content size to expand to accommodate the inner view.
If you have multiple views you want to add to a scroll view, for example laid out horizontally, you'd lock the left side of the first subview to the left of the scroll view, lock the subviews to each other horizontally, and the right side of the last sub view to the right side of the scroll view. Those constraints would force the content size of the scroll view to expand to accommodate all of the subviews and their constraints.
If your question is "How do I put a bunch of UITextFields in a vertically scrolling UIScrollView such that they move out of the way of the keyboard when they have focus", the best answer is:
Don't.
Use a UITableViewController with static cells instead.
You get this scroll-out-of-the-way behaviour for free, AND all the content insets Just Work if your view controller is displayed inside a UINavigationController.
You should organize your layout like this
ViewControllerView contains ScrollView, ScrollView contains ContainerView, ContainerView contains 2 Labels
Then follow 3 steps for make your ScrollView can scroll
Setting ScrollView pin (top/right/bottom/left) to ViewControllerView
Setting ContainerView pin (top/right/bottom/left) to ScrollView
Set Horizontally in Container (don't set Vertically in Container)
Label1 pin (top/right/left) to ContainerView
Label1 pin (right/left/bottom) to ContainerView and top to Label1
HERE is the demo project
Hope this help
The pure autolayout approach works beautifully but it is quite a pain to get set up if you're migrating from non-autolayout. I've done it a few times now and I have a few general tips:
Start small: even if it means recreating your storyboard views, start with just a few elements and build your views slowly, making sure to test that scrolling works after adding a few elements.
Turn off translatesAutoresizingMaskIntoConstraints on everything: this was always the the cause of constraint conflicts for me.
Set your UIScrollView constraints properly: make sure the scroll view is connected on all sides to the parent view, otherwise it just won't expand at all.
After some time dealing with this issue, I finally found a solution. I'm working with universal class sizes storyboards (600x600). I created a UIView (contentView) the size of the scrollView and created constraints to Top, Bottom, Leading and Trailing to the scrollView. Then I clipped the size manually of the contentView to 600x600. The storyboard stopped trying to resize everything and I could work but the view looked awful on the real device or simulator.
I made 2 constraint outlets of this clipped sizes.
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewWidthConstraint;
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewHeightConstraint;
Then in viewDidLoad
CGSize viewSize = self.view.frame.size;
self.contentViewWidthConstraint.constant = viewSize.width;
self.contentViewHeightConstraint.constant = viewSize.height;
Works great.
I spent days trying to find a solution of how to use AutoLayout view an embedded Scrollview, to centre the scrollview in the visible screen, that works across all devices / screen dimensions as well as with screen rotation.
I spent days trying to do it with Autolayout only, and got close but never close enough. So in the end I had to add 3 lines of code per screen as well, in viewDidLoad.
See solution below :
Create the scrollview and fill it with whatever objects you want
Turn on auto layout
Then Centre the ScrollView Vertically and Horizontally
Select the View and then 'Add missing constraints' - this then does its thing
The result is that the a lot of constraints are generated. There are 2 new ones created for the view : 'Horiz space scrollview to View' and 'Vert space scrollview to view' or vice-versa.
Delete the 'Horiz space scrollview to View' so you are now left with 3 constraints on the View. The 2 for entering the scrollview in the view and the one to set a vertical space between the scrollview and the view
Now link the Vert constraint to your code by click and Ctrl dragging it to the header file and creating an NSLayoutConstraint IBOutlet (I called mine constraintVertVtoSV)
Now go to the .m file and add these lines of code into viewDidLoad (play with the padding amount to get the correct vert centering)
if (IPAD)
{
self.constraintVertVtoSV.constant = 150.0;
}
this should now run on all devices and be properly centered and still scroll properly.
If like me you just use static content without counstraints inside the subview, like you can do like this:
override func viewDidLayoutSubviews() {
scrollView.contentSize = CGSizeMake(320, 800)
}
Similar problem I'm having today with iOS 8.4, Xcode 6.4
There a view containing a scroll view, containing a contentView (UIView) containing subviews.
Everything is auto layout everywhere.
The scrollview edges are pinned to the parent views edges with constraints.
The content view edges are pinned to the scroll view edges with constraints.
Originally the content view would refuse to size as the full width of the scroll view. I had to add an additional constraint on the content view to have its width match the parent scroll view. Or I could set a contentView.centerX == scrollView.centerX constraint. Either one of those in addition to pinning the edges suddenly made the content view properly size.
// Either one of these additional constraints are required to get autolayout to correctly layout the contentView. Otherwise contentView size is its minimum required size
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1.0, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0.0))
Pinning the edges of the content view to the scroll view using visual constraints of the form,
let cvConstraints = ["H:|[contentView]|", "V:|[contentView]|"]
I use a routine to iterate through the array and add them to the scrollView.
I faced a similar problem. I set every constrained and was always wondering why it still resizes some subviews. My solution was to set clipsToBounds to YES.
In swift you can use this working solution.
Contraints
ScrollView: Leading, Trailing, Top, Bottom = Superview
ContentView: Leading, Trailing, Top, Bottom = ScrollView. Height fixed/relative to content.
You can set the width constraint(contentView) to equal scrollviews superview, but select remove remove on build time because you will be adding that constraint programmatically. This is just so the IB doesn't complain with warnings.
extension UIView {
func setupContentViewForViewWithScroll(contentView vwContent : UIView) {
//Set constraint for scrollview content
let constraint = NSLayoutConstraint(item: vwContent, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.bounds.size.width)
vwContent.addConstraint(constraint)
self.layoutSubviews()
}
}
And in the View Controller viewDidLayoutSubviews i just call this method:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.view.setupContentViewForViewWithScroll(contentView: vwContent)
}
I know this is a layman's solution and not what Apple suggests in the docu, but it worked for me twice, with different content and can be set up very quickly:
In the storyboard view controller insert UIView.
In UIView insert a Table View, Dynamic, 0 Prototype cells, Style Plain or Grouped.
In Table View insert a Scroll View,
in Scroll View insert content.
Thats it, no settings in the custom view controller.

Resources