UIScrollViews subviews not resizing themselves on Portrait to Landscape Orientation Change - ios

In my app, I have a hierarchy like Main view -> UIScrollView - > UISearchBar. The search bar covers the whole width of screen. But when it switches to landscape the scrollview adjust itself according to landscape and cover whole screen but its subviews like UISearchBar width remain same as in portrait. Plus I'm using Autolayout and I've correctly set their constraints (Leading and Trailing, width (greater than equal to 320) etc) in storyboard.
Also I know there are several answers for this in SO but almost everyone is saying set width again in willAutororate. But I have around 15 subviews in UIScrollview which I think is not possible to set programatically (as increase LOC) plus I think Autolayout must have some solution to it.

Scrollviews don't play very well with constraints. Here's an approach using constraints and Interface Builder that worked for me for having a vertically scrolling scrollview that doesn't require any manual or content size finagling and works with rotation:
Scrollview in a view controller positioned with constraints
A container (UIView) that is a subview of the scrollview positioned with constraints pinning each edge to the superview
Add all your additional subviews to the container view instead. Use constraints. Exceed the height of the scrollview to get a vertically scrolling scrollview.
There is one trick however to get rotation resizing to work automagically:
You have to add an additional constraint to the container view to match its width to the UIScrollview's width. It's strange that you have to do this, since pinning each side to the scrollview should do the trick, but alas it won't work with rotation if you don't add the additional constraint.
Here's what I mean:

try this :
this problem will solve by constraints only. I created a project and by using correct constraints its working fine for me ,
here I am going to show you how to add correct constraint one by one :
add scrollview and add constraints for scrollview only like in the screenshots :
2. now add search bar and add constraints for search bar too,
here below you can find out complete constraints for scrollview and search together:

You could use UIViewAutoresizing mask (autoresizingMask property) of your subviews.

Related

UIScrollView - Need Constraints for x position/width, Need Constraints for y position/height

I have a view hierarchy that looks like this (based on other answers and Apple's advanced AutoLayout guide for working with UIScrollView):
The 2 steps required for ScrollView are:
Set up constraints for position and size (frame) of ScrollView: The same way you do it with any other view.
Set up constraints for content size: By making sure that there are constraints from the ScrollView's subviews touching all edges (leading, trailing, top, bottom) of the ScrollView, if you're doing this in interface builder and not programmatically.
Step 1 worked fine at first and this was the result:
No problems with position and size as expected. I just need to define the content size (content height and content width) now in Interface Builder with Step 2.
Now I add the constraints touching all 4 edges of the ScrollView like so:
Suddenly, the ScrollView doesn't know it's position and size (frame) anymore.
I've looked at other answers and followed the various steps, but can't seem to resolve this issue. Sorry I'm not able to post Storyboard screenshots because of privacy issues
Set the scroll view's top, bottom, leading, trailing constraints to its superview to 0.
Set the view that is inside the scroll view and set its top, bottom, leading, trailing constraints to its superview to 0.
Select the view that is inside the scroll view, go to the size inspector and set the "Intrinsic size" to "Placeholder".
Scroll views can be a little tricky at first. You really have 3 parts:
Actual frame of the scroll view
Actual frame of the subview(s) contained in the scroll view
The contentSize of the scroll view - that is, how far it should scroll in either direction
So, 1. is pretty straight-forward.
The second part also seems straight-forward, except that we tend to "pin" subviews to the inside edges of their superviews. In the case of scroll view subviews, those constraints are what defines the contentSize. You also have to make sure the subviews have a "size".
Starting with just one subview, you would:
set the scroll view's constraints as "normal".
set the size of the subview - just for demo purposes, set it to 100 x 100
pin all four edges of the subview to the four edges of the scroll view
Run the app. Assuming you set background colors so you know what you're looking at, you should see the scroll view positioned and sized as you'd expect... you should see the subview of 100 x 100 sitting somewhere inside the scroll view... and you will likely not be able to do any actual scrolling.
If you go back and change the subview to, say, 100 x 800, and still have its bottom constraint pinned to the bottom of the scroll view (the subview's superview), and run the app again... You should be able to scroll up and down for the full 800 pt height of the subview.
The way to think about it is: the scroll view's content - whether it's one or many subviews - has to define its own size, which will define the scrollable area (the scroll view's contentSize).
Hope that makes sense!

dynamic height of of scrollview subviews in autolayout ios

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)

What are the correct constraints on UIScrollView from Interface Builder? Pure Autolayout from IB

I have been trying to get ScrollView to work for 2 days now, and it doesn't work at all. Most of the suggestions here on SO and other websites say that you need to pin the ScrollView to the root view and then place a ContentView (UIView) inside ScrollView and then pin it to all sides of the ScrollView (so that the scroll size can determine the contentSize... However this does nothing). There's also conflicting information out there, one video says that there needs to be a constraint from the bottom of the ScrollView to the ContentView. Neither solution has worked for me. Here is what I've been doing in most of the combinations I've tried:
UIView -> UIScrollView
Pin all sides of the UIScrollView to the UIView
Create a UIView (name it content view) and place it inside UIScrollView
Pin all sides of the UIView to the UIScrollView
Problem at this point: UIScrollView needs constraints for X or width AND Y or width. The only thing that seems to solve the complaint is setting the UIView inside the scroll view centered horizontally and vertically, but this does nothing to make scrolling work. Another option is setting the UIView equal height and width to scroll view, but again, that does nothing other than remove the complaint.
I don't understand. Isn't pinning the sides, setting the constraints? IB seems to think that this is not the case.
What are the correct constraints needed? All I need is a simple view with stacked controls (to fill out a form) and the screen needs to be able to scroll if the form is longer than the screen.
I'm using iOS for the first time, and building purely from IB for now... minimal code solution would be best.
You are half way there. First you need to decide what you are going to display in the scrollview, you have placed a content view, that needs to have an intrinsic size. You can choose to put there static or dynamic views. Static views will have their size defined at design time, and that will resolve the UIScrollView AutoLayout constraints. If instead you are doing it at runtime with dynamic views you will need to choose a default size for your content view, create an IBOutlet for the width and/or height of your views and then resize them at runtime altering the outlet in viewDidLayoutSubviews. The video you linked explains that quite clearly.

UIScrollView and auto layout not working

I'm trying to make a view scrollable in my app.
O follow exactly the steps in tutorial https://www.youtube.com/watch?v=UnQsFlMGDsI .
The main steps I did were:
Add a UIscrollView
Add a view into UIscrollView (Content View)
Create the margin constraints with value 0 (top, left, right and botton) for UIScrollView
Create the margin constraints with value 0 (top, left, right and botton) for Content view
Create 2 constraints of "equal width" and "equal height" between ContentView and main view
... (Add some text fields)
When I run the app, the scrollView doesn't work
I really can't make it work. I tried many ways to apply a UIScrollView and didn't get it.
As mentioned in the video, the main aim is to automatically adjust the UIScrollView contentSize to the size of the screen or to the size of the content in such way that on smaller devices scrolling is active and on larger devices scrolling is not active because it is not needed.
For this to achieve you've to set proper constraints to the content view so that the height is automatically calculated. From your video its visible that you're not setting the proper constraint to the last UITextFeild (this is important).
You have to give the top as well as the bottom constraint to the last UITextField so that contentView height is automatically calculated.
I have done a sample project which you can check here :
Sample Project
you can do this for working UIScrollView:
1)add a ViewController
2)put a UIScrollView in it
3)from "Simulated Metric" change size to Freeform. change the height to your desire height
4)add auto layouts to both UIScrollView and View (it's not needed)
5)put your controls in view and add auto layouts to them.
this should work :)

scrollview has ambiguous content width on Xcode 6

I can't understand how can I solve this auto layout problem, i have this View:
There is an UIScrollView with the elements you see in the View, but the View gives me this warning:
scrollview has ambiguous content width
I can't understand how to solve this problem, I want the the view is for the full screen size, and I want that the width will be the screen width, how I can solve it?
I observed its fix in XCode 7.3 and it is just 10 sec work. I made a video on it. Check here:
https://www.youtube.com/watch?v=yETZKqdaPiI
All you have to do, add a subview to UIScrollView with same width and height. Then select ViewController and press Reset to suggested constraint. Please check video for clear understanding.
Thanks
This is because you are not providing enough constraints so that Xcode can find Width of your scroll view.
You can see on your screen there isn't any constraints that can be satisfied to find width of scroll view.
You can do it by providing leading and trailing space of Image view which contains fix width. It also can be done with any other views. But i will prefer control which contains fix Height & Width So there isn't require to set hugging priority or Compress resistance.
Put everything in a View and that View put inside a ScrollView.
Editor -> Embed in -> View
The solutions is:
You have a UIImageView at the top. You set the width of the UIImageView to be the same as the width of the root view of the UIViewController
You set the leading and trailing space of the UIImageView to the UIScrollView to be both 0
You set the height of the UIImageView to be the height you want the image to be. And then you set the view mode of the UIImageView to be 'Aspect fit'.
I had the same problem a month ago. Add a constraint that makes the UIView inside the UIScrollView have the same size of the UIScrollView's content width. If you have multiple views inside the UIScrollView, put your UIViews inside a new UIView and make sure the new UIView has the same content width size as the UIScrollView.
Best regards,
I too faced this issue and the only way i got it solved was using the below strategy
Add a scroll view and set its constraint to fill in the screen
Add a UIview inside the scroll view lets call this view as the content view.
In this contentView, set top, bottom, left and right margins to 0 (of course from the scrollView which is the superView);
This should do it now you can follow step 3 and continue with your UI
Place your view inside the content view and add constraints to it accordingly.
Hope it helps

Resources