All the views here (except the nav bar) are in a scroll view. All the scrollview's children have pinned heights and vertical spacing set between them. The top label (Thanks for using...) and bottom button (Toggle) are vertically pinned to the scrollview at the top and bottom respectively. The bottom button is also pinned to the bottom layout guide.
I want a flexible height on the red view. The red view is the only one with an inequality constraint. Height >= 64
The flexible height is working in that the height of the red view automatically expands to 152 to fill the extra space on 4'' devices.
However, I want to expand the height even more. In code, I want to expand the height of that red view to, let's say, 300 when someone taps the Toggle button.
- (IBAction)toggle:(id)sender
{
[self.scrollView layoutIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
self.constraint.constant = 300;
[self.scrollView layoutIfNeeded];
}];
}
When I do this, I get an error in the console. "Unable to simultaneously satisfy constraints." Ending with, "Will attempt to recover by breaking constraint " and it breaks the constraint that I just set for the height of 300.
So....how DO I set the height of that red view to something larger like 300? I assumed if I updated it's height contraint that the contentSize of the scrollView would automatically adjust, but that does not seem to be happening.
You are setting the height of the constraint in code correctly. However, your layout needs some tweaking to get this to work properly.
It looks like you're adding the subviews to the scroll view itself. Instead, you need to add a content view to the scroll view, then add subviews to the content view.
For more information about how to use Auto Layout with a UIScrollView, check out Apple's technical note: developer iOS technotes
In your particular case, I would use Apple's so-called "Mixed Approach". In this approach, you set the content view's frame and the scroll view's content size directly. Calculating the height will be a pain. This involves calculating the height of every individual subview plus margins and spacers.
Related
I am creating a UIScrollView from xib, in which 3 view are there 2 UIViews and in middle an UIImageView. when I am setting constraints Xcode asked to set Y position constrains. But the problem is Y position constraint is blocking Scrollview to scroll down and automatically adjusting the views which looks ugly in landscape mode.
when I am delete that constraint it ask to fix height of subview. I searched a lot but I am new in autolayout so not understanding many of solutions. any help would be great.
You have to set all the height constraints in the content view.
But you also want the height of the Content to be proportional to the screen size.
To do this assign the height constraint of the imageview [equal|proportional|a-computation-of] to the view containing the UISCrollView.
It seems weird to skip levels of herarchy when assigning constraints between two views whose are not direct ancestor/sibling of each other but within a scrollview (at least) it is perfectly acceptable.
You are basically telling the scrollview that it's content has a known size and at same time setting this content to adapt dinamically to the screen size (if the constraints of the root uiview are set correctly)
UIView1
|---UIScrollView
|---UIView2
|---UIImageView [heightConstr.constant=UIView1.height-UIView2.height-UIView3.height-margins]
|---UIView3
This is the basic idea, to be done programmatically, then you can explore other solutions.
Unfortunately the constraint system in ios pretty much sucks when it's up to more complex equations involving more views for a single constraint.
UIScrollViewcan be tricky when adding constraints. You should always add a subView that will behave as the content view for your UIScrollView and all your subsequent views will go inside this content view.
UIView1
|---UIScrollView
|---UIContentView
|---UIView2
|---UIImageView
Set your UIScrollViewconstraints as you would normally but set your content view to have leading, trailing, top and bottom to the UIScrollView but also add two more constraints which will be equal width and equal height to the viewController.view but will have a low priority (So that whichever direction your content will increase in, that constraint will break and automatically increase the content size of the scroll view by taking in the inferred height of the content view). Now go on and add constraints on all your subview as you normally would. Which i'm assuming would be:
Your topmost view will have top and leading and trailing to its superView and also a fixed height.
Your bottom view will have leading, trailing and bottom to its superView and also a fixed height.
Your UIImageViewwill have a leading, trailing and top to top most view and bottom to the bottom view.
Edit:
Here is the screenshot just in case (To show the view hierarchy with the content view's constraints in the inspector)
I want to do something simple, yet Apple loves to overcomplicate things for developers (quite ironic). I want to create a vertically scrollable screen. Basically a longer screen that I can scroll through. The problem is that it either doesn't scroll or the content (a label for demo purposes) is fixed on the screen (e.g. centered).
I looked at multiple tutorials but still didn't fully understand it because the inner workings aren't fully explained.
So from what I understand, it goes the following:
You place a UIScrollView on top of the main UIView
You set the UIScrollView's margins to 0-0-0-0
You place a content view UIView inside the UIScrollView
You set it's margins to 0-0-0-0 related to both the main UIView and the UIScrollView
You set the UIScrollView and content UIView's height & width (in my case I chose 1000 for height and screen width for width since I want only vertical scroll)
You set the UIScrollView.contentSize to something bigger than the screen
You add the content and align it to the content UIView
So what am I missing or adding when I shouldn't? If anyone can explain how this is done quickly, please do so.
Quite a lot of this is wrong:
So from what I understand, it goes the following:
You place a UIScrollView on top of the main UIView
You set the UIScrollView's margins to 0-0-0-0
You place a content view UIView inside the UIScrollView
You set it's margins to 0-0-0-0 related to both the main UIView and the UIScrollView
You set the UIScrollView and content UIView's height & width (in my case I chose 1000 for height and screen width for width since I want only vertical scroll)
You set the UIScrollView.contentSize to something bigger than the screen
You add the content and align it to the content UIView
There are various strategies for making a scroll view scrollable under auto layout. The "content view" strategy is perfectly valid, and very convenient, though it is not the only possible strategy. Since you seem to imply you want to use it, let's use it:
Pin the scroll view's top, bottom, left, and right with constraints to main view. Typically these constraints will have a zero constant, but no law requires this.
Give the scroll view exactly one immediate subview, a "content view". Pin the content view's top, bottom, left, and right with constraints to the scroll view. These constraints must have a zero constant.
Give the content view height and width constraints. Set their constant values absolutely. Experimentally, use large numbers. As you've said, width of zero and height of 1000 will give you vertical scrolling on a screen smaller than 1000 height.
Now stop. Don't add any more constraints, and don't set the scroll view's content size in any other way. You are finished. The scroll view is now scrollable, even though there is nothing visible inside it — provided the height or width constraints constant values are larger than the actual height or width of the scroll view at runtime. And you can run the project and see that this is true.
You are now free to populate the content view.
You don't have to put a UIView inside the scroll view. You can just add whatever objects you want and set objects frame within the scrollview. The scrollable area is set by the contentSize property of UIScrollView.
Some things you will want to make sure to do:
1) Add <UIScrollViewDelegate> to your .h file
2) set scrollview.delegate = self;
3) Set scrollview.contentsize = CGSizeMake(something bigger than the screen)
4) make sure the scrollview is scrollable with scrollview.scrollEnabled = YES;
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];
}
}
I have a scroll view that takes up the entire screen for a view. In this scroll view, there are several text fields stacked vertically. Due to there being too many of these text fields, I am using a scroll view, so the user can scroll down. I am using Xcode's Preview so I can set the view up to work on many devices. The problem I have is that I want these text fields to change horizontal size to fit, so there is no horizontal scrolling; however I can never get them to change size. Rather, the scroll view just lets me scroll horizontally.
I set this up in Xcode's interface builder (the scroll view and the text fields), and had Xcode apply all of its suggested constraints. Then, I put in a constraint for each of these text fields that set their right edges to be a set distance away from the scroll view (I could not set a distance from the actual view because the scroll view is the superview). These constraints did not clash with any existing constraints. There was no width set for any of these text fields by Xcode's suggested constraints.
Then in the viewDidLoad: method: [scrollView setContentSize:CGSizeMake([[UIScreen mainScreen] bounds].size.width, scrollView.contentSize.height)];
This in an attempt to force the scroll view to use the super view's horizontal width.
I am sorry about the vagueness of my question. Essentially, I need a way for text fields in a scroll view to resize horizontally to fit the screen.
You say that you apply the "edge" constraints for the text fields in relation to the scroll view.
You should add them in relation to their superview i.e. The scroll iew's content view.
When dealing with autolayout and scroll views, try to think of all the subviews as trying to define the content view's frame in an unambiguous way so the scrollview can "resize" properly.
Apple has set up a technical note for this kind of issues.
https://developer.apple.com/library/ios/technotes/tn2154/_index.html
I'm using AutoLayout and had trouble with a scrollview still scrolling horizontally that was slightly narrower than screen width.
This is my fix:
-(void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.scroller setContentSize:CGSizeMake(MIN([[UIScreen mainScreen] bounds].size.width, self.scroller.frame.size.width), scroller.contentSize.height)];
}
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.