iOS - Scrollview and equal widths does not work - ios

I'm facing a problem with Autolayout. I want to setup a simple scrollview controller, with the following pattern View -> ScrollView -> View -> "All my content" explained everywhere when searching on the web.
Here is my Storyboard :
In theory everything is correct, but the Equal Widths constraint seems to behave very strange. I made a videos for you to be able to see :
https://www.youtube.com/watch?v=lAezdxg5L4E&feature=youtu.be
PS : The view controller is not linked to a *ViewController.swift, so there is no self-made code behind this controller.
How to solve that ? Thank you.

You have laid out your constraints for the wCompact hRegular size class, which applies to all iPhones in Portrait. When you switch to landscape, none of the constraints are installed which explains your issues. Convert your constraints to wAny hAny and all will be good.
After recreating your problem, I did this to convert to wAny hAny:
I went to each constraint and turned off the tick mark next to wC hR installed. You'll also need to do this for the ScrollView and Container as well.
Then I set the size class back to wAny hAny.
Then I went back to each constraint and ScrollView and Container and turned on the tick next to installed and deleted the wC hR one by clicking on the "x".
If you do this, your green Container view will appear in both Portrait and Landscape and it will scroll vertically.
Two hints:
If the reason you set wCompact hRegular was that you find it distracting to work with a square viewController, then click on the viewController in the Storyboard and set the Simulated Metrics Size to iPhone 4.7-inch in the Attributes Inspector.
You should really set Equal Widths between the Container and the ScrollView instead of setting Equal Widths between the Container and the top level view. In your case it doesn't matter because the ScrollView and its SuperView have the same width. But if your ScrollView wasn't the entire width of the screen, then you'd want to constrain the Container width to the ScrollView width to prevent horizontal scrolling.

If you are talking about the contentView(container in your app) of the scrollView if doesn't work like that.
eg. if you set contentView inside scrollview to equal width and height of the scroll view if wont work.
If subviews of containerView is complicated, normally I design contantView outside of scroll view. (see screen shot) and set it programmatically.
Or I just set auto-layouts equal width to both scrollView and container of scrollview too. (see screenshot)

I see you use size class, possibly you don't have contraint for iphone landcape

Related

ScrollView is missing constraints

Swift 5/Xcode 12.4
My app uses a UIScrollView to zoom its child UIImageView (which is filled through code). This part works but the ScrollView keeps complaining in XIB that it's missing constraints for the x/y position or width/height.
As you can see, the ScrollView has a top, leading and trailing constraint and the width is set to equal the height. From my understanding it knows its dimensions and position because of these constraints but apparently it's not enough. I do NOT want to center the ScrollView vertically and as the app has to support both iPhones and iPads, I also can't just set a fixed "bottom space to" constraint for the ScrollView.
I already tried to set the ScrollView's width to the ChildView's width and center it horizontally in it but the warning still didn't go away.
I've seen suggestions to put the ScrollView's contents inside another UIView but in my case it's only a single image and if I embed it inside a view, then the zooming breaks.
Why is the ScrollView still missing constraints and how do I fix it (without changing the overall layout of this ViewController)?
A UIImageView (without an image) has no Intrinsic Content Size.
If you're going to be setting its Width and Height constraints via code, but you want to get rid of the IB layout complaints, give the image view a Placeholder:
Edit
If you want the view(s) to be sized in IB, but you're going to change the constraints at run-time, you can either:
Connect the constraint to an #IBOutlet and change the .constant via code (more problematic to change the multiplier if needed, so probably not the way to go)...
Or...
Give the view constraints in IB but set them as Placeholders by checking "Remove at build time":

Auto layout for uicollectionview

I have a UILabel in my storyboard which i want to align from bottom and whose width and height want to get adjusted in portrait and landscape.
For this, i dragged in a UILabel pinned its leading space, trailing space, bottom space to its superview.
I did not pin its width and height since i wanted its width and height to be changed during its landscape rotation.
With this i got a warning in story board where i have selected to update frame, which automatically adjusted the frame and made it work correctly.
Now i am trying to achieve same kind of behaviour with UICollectionView but this is not working as expected, instead it is giving out some errors saying 'misplaced view' and 'missing constraints'.
I am aligning buttons in 2 rows and 3 columns in the collection view in portrait mode and want to align all the 6 in single row in landscape mode, so if i pin the height here.
The problem is it will go good for portrait mode but in landscape the height will seem higher. Any help on how this could be achieved.?
You got errors because you did not added the constraint for the collection view top layout or height or aspect ratio. it is necessary to assign all side constraint so the view will automatically layout according to the constraint. if you miss one it will give you error or warning. Look you want dynamic height for collection view. If you want to achieve this for all the devices like for all iphones then you need to pin the height and make a outlet of the height constraint and change it in your viewDidLayoutSubviews method. select the collection view then go to size inspector and double click the height constraint. this will show you the constraint on the document outline. make outlet of that and change that constraint according to your need like on portrait or landscape you can calculate with logic. you might need to change the constraint according to the orientation change. follow https://stackoverflow.com/a/24072010/4030971
i know that will be great if all those stuff work only with some constraint but i found this way easier for me.

Implicit Constraint iPhone Portrait Screen Height

I tried to create a custom freefrom view with interface builder.
I have a UIView which is containing a UIImageView and UILabel.
I set the constraints to adjusting the Label according to the Image etc and a margin to the superview.
Now I want the superview to exactly fit the subviews. But when I press Editor -> Size To Fit Content, the superview is not resized completely and the constrains are in conflict. What there appears is a implicit constraint ("iPhone Portrait Screen Height"), which can not be altered/deleted. See Screenshot below:
While not ideal, depending on how your XIB is structured and how you are referencing the view, you could create a "scratch pad" view and place your custom view inside of that just to see how everything will layout. That is if you're setting the view to an outlet defined in the XIB's File Owner, you can just connect it to the view you've created inside the "scratch pad".
For example, I created a container view with a square and a switch inside. The top example complains of conflicting constraints and doesn't layout correctly, while the bottom example shows the same thing centered in a throw-away view. Again, not ideal, but it's working for me.
Edit: I just realized that some size class constraints may be lost once the "scratch pad" view is discarded so that is another wrinkle to consider. Still looking into this.
Just to make it simple forget the label for the time being. You have already added the width and height constraint of the image view, now instead of using sizetofit content, try adding leading, trailing, top and bottom constraints between the image view and it's parent view. With that your parent view should fit the image view.
The same technique (constraints to parent view) can be used to get it work with the image view and label together.
I noticed that when I physically dragged the superview's width and height to satisfy the constraints, the red constraint errors went away along with the "iPhone Portrait Screen Width" constraint. In other words, my constraints dictated that my subview be bottom aligned with its super view. If I dragged the superview's bottom edge up to align flush with the subview, the errors went away. Still seems buggy and unintuitive.

UIScrollViews subviews not resizing themselves on Portrait to Landscape Orientation Change

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.

iOS Scroll View, Container View - auto layout issue

I'm using storyboards & auto layout. I have a Container View in a UIScrollView. The Container View allows me to layout a long (320, 1000) view in the storyboard. I set the content size of the UIScrollView to (320,1000).
I pinned the following constraints on the ContainerView to the ScrollView:
Width Equals: 320
Height Equals: 1,000
Top Space to: Superview
Align Center X to: Superview
Xcode insists on adding an additional Constraint. It adds a Bottom Space to: Superview Equals: -432. It will not let me delete this constraint! I'm not sure if this affects the issue below.
Everything works fine on the 4" screen of my iPhone 5 and Simulator.
My problem comes when I test it on the 3.5" screen in the Simulator & my iPhone4S. The scrolling content size becomes restricted to (320, 568), losing the bottom section of my ContainerView.
Can someone help me understand why this doesn't work on the 3.5" screens?
Received the answer from Apple Tech support. It still gives me an error in Xcode, but it functions on 3.5" screens now. Here's the answer:
I'm not sure why interface builder decided to relate the bottom of the container view to the bottom of the scroll view's content view minus 432. You can not remove this constraint because it is necessary for the layout to be fully defined [1]. However, if you promote that constraint to a user constraint, you can edit the constant value to zero. This will correct the issue where the bottom part of your content was being cutoff.
In Interface Builder:
1) Select the Container View
2) Switch to the Size inspector
3) Click the gear icon next to the "Bottom Space to: Superview; Equals: -432.0" constraint.
4) Choose Select and Edit from the menu.
5) Enter a value of zero in the constant field.
[1]: See the In Depth Explanation section of Technical Note 2154 for more information. https://developer.apple.com/library/ios/#technotes/tn2154/_index.html#//apple_ref/doc/uid/DTS40013309
When you embed a view into a UIScrollView in InterfaceBuilder, then there's a constraint automatically set. If your view is "longer" than the screen in portrait, it wont scroll at all.
But if you rotate the screen, you'll notice the ability to scroll a little.
To get UIScrollView going in AutoLayout look into your constraints.
Find "Vertical Space - Scroll View - View" and set it from "constant" to "auto" - fixed everything for me.

Resources