UISTackview constraint error in a UIScrollview in viewcontroller - ios

I was trying to add a UISTackview in a scrollview. I believe the UIScrollview setup is right as the following screen has scrolled. Please note that it does not have any stackview, I have added a button with big top constraint so that I can see whether the scrollview works or not.
Next, I added the stackview and just added the top, left, right constraint but not bottom constraint like the following image. However, since there is no bottom constraint, the scrollview does not work.
When I added the bottom constraint, it shows the error like the following image because none of the textfields has height constraints.
If I change the distribution to "Fill Equally". The textfields are taking too much blank spaces depending on the screen size.
How can I use the stackview inside the scrollview. I want to use it as I want some of the views hidden based on conditions and claim the space. Any suggestion would be helpful. Thanks

Your second image is correct - but you need one more constraint.
Add a constraint from the Bottom of the Stack View to the Bottom of View (its superview), but set it to >= 0
A couple of tips...
rename your UI elements... it gets very confusing to refer to elements by default generic names (you have more than one View, for example).
give your objects contrasting background colors during development... makes it much, much easier to see the frames.

Related

making an auto layout of UIimageView and textview inside scrollview for iOS 10.2 in xcode8

I am making a note taking app in xcode8 for iOS 10.2. The note is consist of a textfield, textview and imageview. I am adding textview and imageview in separate scrollviews (to provide the facility of zooming and adjusting image). Then I have added both scroll views in a stackview to ensure that imageview and textview stands side by side in a landscape mode. To do that, I have added variation to axis property of stackview( width=any, height= compact and Gamut=any, and set that to the horizontal, as shown in right corner of screenshot to see view hierarchy without any constraints).
I have tried many constraints but, every time it fails to adopt. Let's take an example, I am adjusting size of the scrollviews on the size of content(by setting top,bottom,leading and trailing constraint), the stack view is adjusted to the main view. Now, the only thing that needs to be adjusted is text view and imageview with respect of stack view. But, here is the tricky part If I include a fixed trailing constraint of text view to the stack view; it will work in portrait mode.As soon I turn into landscape mode that constraint will not work(the trailing constraint which have 0 distance from stackview) because the edge will be side to the imageview not to the stackview(because I am putting image and text side by side as explained above) which will make textview larger than required, same goes for imageview's leading constraint to the stack view and vertical distance constraint betweem image view and textview.I think the root of the problem is I have made a variation to the axis of a stack view (in order to get text and image side by side in landscape mode) but, that was necessary part.Can anyone have solution for this? Do you think there can be other problem? Should I choose Intrinsic Size of scrollviews to placeholder option or let it be system default?
Thank you.
So I hope I understand the question and I will try to walk you through what I understand you hope to accomplish. I preface this by saying I just started using UIStackView because of backwards compatibility.
Note. To get the magic of ScrollView with AutoLayout I almost always embed them in another UIView. There are reasons to not but in this case you will see how valuable this is to AutoLayout.
Step 1) Drag your UIStackView and add Top,Bottom,Leading, and Trailing. Now add 2 UIViews and set the UIStackView to Fill Equally. It will now look like the image(Background colors to check your work).
Step 2) Now add a UIScrollView to each of these UIViews. Add Leading,Trailing,Top,and Bottom on each of these.
Step 3) Add a UITextView and UIImageView to the ScrollViews respectively. Now Autolayout is mad at us :( but we will fix that.
Step 4) Drag from the UIImageView to the View that is holding the UIScrollView(First Set of Views we added). See image
-Choose the option to add Equal Widths. See Image
Repeat the same step but add Equal Heights. Now add Top, Bottom, Leading, and Trailing to the ScrollView.
Step 5) Repeat exact Step 4 with UITextView
Your final view hierarchy should look like this.
Now you can rotate your UIStackView and do what you want I think.
And Horizontal
Side by Side Preview
I did add a <= 0.1 equal heights multiplier on the textfield at the top but I don't know if that was necessary.
Enjoy.

Swift - UIScrollView Scrolls Partially

My problem is slightly different from other's 'Swift UIScrollView' problems when using auto layout:
Problem:
Unlike others, when I run my app, it scrolls. My problem is that the scroll cuts off the bottom 20-30% of the content. I can pull to see the buttons did build and are down there, but when I let it go the scroll snaps back to a false bottom which cuts off my content!!! I've been trying, for days, to fix it to scroll the entire height but it continues to cut off!!
Description of app:
I used auto layout to layout 6 buttons and labels. Each button a rectangular image, with a label directly beneath it. (sorry, the site won't let me post pictures!)
I have my views arranged like this:
MainView > ScrollView > ContentView > Buttons & Labels
I have my contentView pinned to my ScrollView and my ScrollView pinned to my MainView. My buttons and labels all have constraints that are building correctly, to create a list that looks like:
Rectangular button
Label beneath it
Spacing
Rectangular button
Label beneath it
Spacing
Etc.
Can anyone tell me why I can't scroll the full length of the view?
Your description of how your items are constrained is vague, so I'm going to list all of the constraints you need to make this work. Then you can compare what you have to what you need and adjust accordingly.
Your ScrollView should be pinned on all 4 sides to the MainView. (This isn't absolutely necessary. You can constrain your ScrollView however you want, but make sure it can grow as the device and/or orientation changes).
Your ContentView should be pinned on all 4 sides to the ScrollView with offsets of 0.
Since you want your ScrollView to scroll vertically only, constrain the width of the ContentView to the width of the ScrollView using an Equal Widths constraint. To do this, in the Document Outline view, Control-drag from your ContentView to your ScrollView and select Equal Widths from the pop up.
The height of ContentView will be set by the sum total height of everything in it. In order for this to work, your topmost button needs to be pinned to the top of the ContentView, all of your buttons and labels should be pinned to their nearest neighbors, and the bottommost label should be pinned to the bottom of the ContentView. In addition, all of your buttons and labels should have constraints for their widths and heights. I would suggest setting an explicit width constraint and explicit height constraint for your buttons and centering them horizontally in the ContentView. For your labels, set an explicit height constraint and pin the left and right edges to the ContentView.
If you have these constraints and no other ones, your ContentView will be properly sized.
Using contentView, like you said, usually fixes the issue. So chances are you need to take a second look at your contraints. Maybe try this solution in a clean/new project to see that it works. (it does work). My guess would be that some of your constraints conflict each other.
Otherwise I think it would be a good idea to setContentSize of your scrollView in your viewDidLoad.
Another hack would be to place 2 UI objects with their alphas set to zero on the right top corner and left bottom corner. This would hint scrollView to set its contentSize.

Why isn't this UIScrollView autolayout working?

I have a simple program with a UIScrollView, and one UITextField inside it. I constrain the UIScrollView to have 0 space on all it's four sides, which I thought would make it fill the screen. And I constrain the text field to be the standard space from the edges:
But when it runs, it does this:
I see the technical note, but I don't understand it yet.
The field will fill the screen if I give a width=280 constraint, but that goes against the spirit of autolayout. I want it to adapt to the width of the screen, not be hard coded to the 280pt width in the storyboard. How to do that?
Here are the layout errors:
I found an answer to my own question.
The answer is contained in the tech note, but in my opinion not explained in enough detail. This blog post helped me: http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/
Summary: put a width constraint on the text field to shut up the IB errors, but then check the "Placeholder, remove at build time" checkbox for the constraint (in the attribute inspector in IB). Then you can add better constraints programmatically, in the view controller's viewDidLoad method. In this case I want constraints that connect the text field's left and right edges to the scroll view's superview edges (and thus the screen edges). You apparently can't make constraints like this in IB. With those two constraints, it all works correctly, even as the screen is rotated.

AutoLayout - how to bind two view and change size accordingly

i want something who seems simple at first glance, but i can't figure out how to make it nicely from IB.
I want something simple, let's say i have two view into one parent (a view container that hold the two children). What i want is that they are each connected to vertical space at 0 px (one to his top the other to the bottom of the other). So that when one of them change his size the other occupy the remainder size, and so there're will still be connected at 0 pixel each other.
I've put two screenshoots of what i want.
I've tried lot and lot, and nothing is working like i'm expecting.
What is strange that even if i put the priority at the vertical space, the other constraints take priority, and i just get a warning from XCode that my verticalSpace constraint is wrong.
Could someone help me ? I didn't find a specific tutorial on this kind of view managements.
Thanks
* EDIT *
Ok i figured out:
I finally read the entire tutorial of Ray as suggested, and it helped me a lot (to my defense, i have read before the IOS official documentation about constraints, and it has confuse me more than helped me). To me, what was hard to understand is that now you can't change UIView by frame but now by constraint. When I understood this, it was really easy to make the changes.
By the way i tried the #Handsomeguy's response, and it worked like a charm.
I think you'll need at least one height constraint (with IBOutlet to your view controller) on one of your views... when you change its constant value, the other view should automatically change. You can try on storyboard first, and then write down the logic. But without an height constraint on one of them I don't think it will ever work.
I was able to do it by setting constraints in interface builder:
vertical spacing: top layout guide -> yellow
vertical spacing: yellow -> red
vertical spacing: red -> bottom layout guide
height: yellow
Set an outlet to the height constraint, then to change the height of the yellow view just use _height.constant = NEW_HEIGHT
You can probably omit the height constraint if the top view reports it's intrinsic content height appropriately.
Use autolayout. You need the following constraints:
both views pinned to left and right edge of containerView
redView top pinned to containerView top
yellowView top pinned to redView bottom
yellowView bottom pinned to containerView bottom
height constraint on **either* redView **or** yellowView!
This is very easy using this category:
https://github.com/jrturton/UIView-Autolayout
UPDATE
I just noticed you said you wanted to do it in IB. You can use the same principle here, but I find it is much more convenient (and also easier to read later) if you use the category mentioned. There will be very few lines of code, and the code will clearly show the intent.
** UPDATE 2**
An explicit height constraint may not be necessary if the intrinsic size on one view is changed. This depends on what kind of views the yellow and green views are.
Without auto layout it would be as easy as putting an anchor-bottom on the yellow view, and putting an anchor-top on the red one. Now, when you change the parent view, the views would resize 50/50.

UIScrollView behaves different depending on fullscreen or not?

When applying auto layout constraints to a UIScrollView, i´m given an error message if the scroll view is laid out to be full screen, but not if it has "margins". I´ll illustrate with 2 examples. In both examples i apply leading and trailing space to the superview and add top and bottom space to layout guide.
Example 1 (behaves as i expect.)
The auto layout constraints are blue, everything is in order
Example 2 (weird behaviour)
I stretch out the scroll view and apply the same rules as in example 1, but now 1 of the constraints ends up different. The "top space to top layout guide" is added as "Vertical space - (-548) - Top layout guide - Scroll View".
And then Xcode complains that i need "constraints for y position or height" for my scroll view.
Can anyone explain why this is?
Unfortunately, I think this is a bug in Interface Builder in Xcode 5. When you try creating a constraint from the top of a view to the top layout guide, IB usually (incorrectly) adds a constraint from the bottom of the view to the top layout guide.
To get around this, try first resizing the scrollView so the top edge of it is much lower down in your viewController:
Then try ctrl dragging from the scrollView to the viewController, and adding a constraint to the top layout guide. You can then select this constraint and adjust the constant in the inspector so that the scrollView aligns with the top of your viewController:
Alternatively, create your constraints in code :)
Just select the scroll view and manually create constraints for the top, left, bottom, and right edges.
What is happening here is that the automatically created constraints don't make sense, in that they do not fully define the size of the scroll view, only its position.
Following your original example with the scrollview smaller than the containing view I noticed that XCode was actually adding one of the constraints wrong in my case, when I selected "Top space to top layout guide" it was adding a "Bottom space to top layout guide" constraint with a large negative value. I can see something similar from your second screenshot.
My solution was to follow your example with the UIScrollView smaller than its container. I then manually dragged out the constraints, resized the UIScrollView to fit the container. The final step was to take the now correct constraints with the wrong constants and set them all to be 0.
Hope that helps, I'm still working on fixing the problem I had but I noticed this stage was similar to what you posted.

Resources