Centering View between neighbors using autolayout in IOS - ios

I am attempting to layout a screen design using constraints (auto-layout) from interface builder and hope to avoid coding constraints, but I would accept an answer for either case I guess.
I have two subviews in a contained in a top level view. I want to fix vertical distance of the first subview to the top of the screen (I was able to accomplish that - common use case for a vertical space constraint). I want the second subview to float (vertically) in the center of the distance between the bottom of first subview and the bottom of the screen. The idea is that the design responds somewhat to iPhone 3.5" vs 4" dimensions.
I am having trouble defining a constraint or set of constraints that would accomplish this.
I have tried setting inequalities on the vertical spacing constraints between the second subview and the top of it's neighbor (the first subview) and the bottom of the superview, and playing with the priorities of those constraints.
An idea that was suggested in a few other related posts on SO is to use a container that is pinned to the bottom of the screen, as well as the pinned to the bottom edge of the first subview, and then center my second subview in the container. I was hoping to avoid complicating the view hierarchy if possible, but maybe that isn't easily avoided.
Any thoughts or suggestions?

UPDATE
This answer describes how to do this in Xcode 6.0 (and probably works in Xcode 5.0 and 5.1).
ORIGINAL
If you want to do this with auto layout, you have to add at least one spacer view. It doesn't have to be the superview of the vertically-centered view (or any other view), so it has a pretty minor effect on your view hierarchy.
I recommend not trying to set up constraints in Interface Builder in Xcode 4.6.3. It's just too painful. But if you really must, this is doable.
Create a spacer (a plain old UIView) from the bottom edge of the top-hugging view to the bottom edge of superview. Set it to hidden. Give it constraints to the top-hugging view and the left and bottom edges of the root view, and pin its width. My spacer width is 10:
Add your middle view (here, a button). Give it a “Horizontal Center in Container” constraint. Then select both the middle view and the spacer view and give them a “Vertical Centers” constraint:
Note that if you drop the middle view when IB is showing the correct guidelines, it will set these constraints for you.
You can test by enabling resizing for descendents (but not siblings & ancestors) and resizing the root view in IB. The middle view will remain centered between the top-hugging view and the bottom of the superview:

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 - centre a number of views vertically without dummy spacer views

Say I have 2 views (labels or textfields) with varying heights positioned above each other (not on top). I would like the group centred vertically in the superview.
I know I could use a dummy spacer view above and below and set equal height in storyboard. I'm no expert, but this doesn't seem right to me.
Can it be done in storyboard by setting the top constraint for the top view equal to the bottom constraint of the bottom view?
If your subviews' heights will change at runtime (either because you change the number of lines of text in them, or because you support Dynamic Type like a good iOS app should), then no, you cannot do this with just constraints. You either need an extra view or you need to change the constraint constants from code. If you go with an extra view (which I recommend), you can do it with a single extra view.
The simplest solution, if your deployment target is iOS 9 or later, is to put your subviews into a vertical UIStackView and center the UIStackView in the superview. You might not need any constraints directly on the subviews depending on the layout you want.
If you can't use a stack view, you can use a spacer view. First, set up vertical spacing constraints between your subviews to glue them together with whatever padding you want. Then add a spacer view next to the subviews. Set the spacer view to hidden. (Hidden views still participate in layout.) Constrain the spacer's top edge to your top subview's top edge, and constrain the spacer's bottom edge to your bottom subview's bottom edge. Then constrain the spacer to be vertically centered in its container (which should be the superview).
You also need to add horizontal constraints on the spacer to keep Xcode from complaining, but the horizontal size and position don't really matter since the spacer is hidden. So just put it somewhere convenient.
Here's the final set of constraints and layout:
The spacer is the skinny pink view.
You can achieve it easily via center vertically, control and drag the object you want to centre in Storyboard, choose center vertically in container. This way you can centre these subviews in superView individually. If you want to centre these subviews together, you can create another containerView to contain these views(labels, textFields), then centre the containerView in superView.
Hope this help:-)
Control and drag in Storyboard
Center three subView individually.
Center them together with a container view

Auto Layout Not So Auto

I have the most basic set up possible. See pic 1:
Believe it or not this is my first project using AutoLayout, I have created everything prior programatically. This basic set up is literally a UIWebView with 1 custom UIView positioned at the bottom. Previously I was using a tool bar that handled everything for me and had no issues with constraints whatsoever. However, the tool bar created discrepancies for event handling when adding a UILongPressGesture to the subview of the UIBarButtonItem so I decided to convert the tool bar to a UIView (Even inserting a UIView into a tool bar, it naturally converts to a button item) for easier handling. But run-time, the view gets pushed off screen by half of the UIView size (48px) See Pic 2. Then when I add buttons, it just gets worse:
I have reviewed the documents and the support HERE with no results. I've spent about 24 hours in total researching it and learned a lot, so my efforts aren't in vein. I KNOW by 'Adding Missing Constraints', the constraints are just recommendations based on the current set up, they aren't concrete in all cases, so I did try to create my own with control drag after reviewing the documents but my set up concluded with no different results, and exponentially more sloppy. So I decided to include the populated constraints by Xcode below :
UIWebView Constraints
Custom UIView (toolBar) Constraints
Any solid starting point recommendations? Does Intrinsic Size have anything to do with it?
EDIT : WORKING CONSTRAINTS I didn't realize you could simply omit a constraint. It seems the culprit was adding one to the top layout guide.
Just for answerer #Matt :
Constant 0 result : there are small gaps at edges
-16 for leading space/trailing space results as a true toolbar emulation in my case with no outstanding warnings or issues. Thanks
Let's talk about the view at the bottom of your interface and how you would use auto layout to position and size it the way a toolbar would be positioned and sized.
To use auto layout, you need to supply sufficient info to determine both position and size. This view is a subview of the view controller's main view. The main view will be resized depending on the screen, so we want to use auto layout to resize the subview ("toolbar") as well. This is what auto layout is for!
So constrain subview leading edge to the leading edge of the superview, and constrain subview trailing edge to the trailing edge of the superview, both with a constant of 0. Now the right and left edges match the superview!
That takes care of horizontal position and size.
Now let's talk about vertical position. The position should be the bottom. So constrain subview bottom edge to the bottom layout guide of the view controller, again with a constant of 0. Now the bottom of the view is at the bottom!
The only thing we don't know is the top of the subview. This, in our situation, is the same as knowing its height. So give the subview a height constraint, set its constant to a reasonable value like 40, and you're done.

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.

How to use ScrollView and ContainerView with Autolayout checked

I have trouble implementing scrollview with auto layout:/
Here is simple "Hello World" project with that problem: http://www.sendspace.com/file/cg96by
But the problem… I need to create scrollview, but also I need to use auto layout. So I created pure single view application, added (like I saw in some tutorials) Scrollview (the same size as main view), added constraints (all zeros) and then add Container View (the same size as scroll view), add constraints and.. It's didn't work:/ It doesn't scroll. Here is the screen of that situation:
Now, when I delete two constraints named: Center X and Y Alignment (marked on the screen), it works perfectly, but Xcode5 doesn't quite like it :/ and shows some errors like on the next screen below.
Why does he want width and heigh 0 ?!
Actually ContainerView doesn't matter. I've also tried with image view. When you select "Add missing constraints" it also add Center X and Y Alignment. And scroll doesn't work. When you delete them, scroll works but you have this warring:
Ok, I find manually adding the autolayout constraints to be quite confusing, using the "Add New Constraints" button at the bottom really comes in handy, try this, after you get each view where you want it use that way of adding layout constraints for each view (ie scrollView, containerView, UIImageView) I did this, and heres the example, select each constraint as I have so that the top, left, bottom, and right edges are set, this should do exactly what you want.
You will probably want to erase all your current constraints and then implement them this way.
heres the layout like you want http://cl.ly/image/463k2043401L
and heres the example adding the constraints: http://cl.ly/image/472l2V0l3N1L
To keep it dynamic so that you can rotate it, you will want to do the above for all view BUT the container view... then If you control drag from container to scrollview with no constraints, you can add all of them that it suggests except for the height and width at the bottom, that satisfies any missing constraints and should do the trick, It will center the container inside of the scrollview and keep it pinned to the top, bottom, left and right, and it should dynamically change with your scrollview content size.
http://cl.ly/image/1o3k1e452W0g
Sorry for the confusion, hope this helps!
I had a similar problem and i found relative simple solution from within Interface Builder using pure Autolayout without any code.
For proof-of-concept at first remove any constraint in View Controller to if see this works.
This is sample layout:
View (main view of my UIViewController)
Scroll View (UIScrollView)
Container View (UIView)
Content View (e.g. UIImageView)
A. Scroll View width/height should be smaller that Container View width/height
B. Container View should have some determinated width/height (may be explicit width/height )
C. Do Control-drag Container View to Scroll View and add only:
Leading Space to Container
Trailing Space to Container
D. Check out those two constraints and set "constant" value for both to 0
E. Run app and

Resources