How to constraint elements in view? - swift

IMPORTANT: This is not a main view but a view I added on the main one and it has its size.
I'm trying to constraint this view in order to make it resizable on every iOS device. I want it to look exactly how you see it.
I followed multiple guides online but even if I do exactly what I see it doesn't seem to work for me.
Here's what I tried:
I set the cancel's button width, then I constrained it to the view (trailing, bottom, leading) and vertically in container. I did the same for the one above it but the bottom constraint was attached to the button.
As regards the view with a lot of square buttons I:
Constrained the view to the button below it (bottom), set its width, placed it vertically in container, top space to safe area (I have a navigation bar above my view) and trailing and leading space to view.
As regards the buttons inside my view I set equal widths and hights for each of them and then I constrained them all top leading trailing and bottom (they all have a space of 7 between them or their view).
None of this works since the blue sky view either becomes bigger and wider, either goes outside of the screen, either everything gets very weird... How could I do?

I think this question is a bit tricky to answer. But I'll try my best :D
So, the first thing I would do is to put the pink squares inside a stackView and let autolayout help us a little. Then I would constrain the blueSkyView.top .leading and .trailing. After constrain the stackView .top, .leading, .trailing, .bottom to the blueSkyView, so that blue sky view could enlarge to fit the stack inside.
Then constrain the buttons to the bottom, just like you made. Consider using some constraints of Greater than from blue sky to Random Color button, for example, guaranteeing they will never overlap.

If you want to make this view a square for very time while using different devices, you need to give a height constraint for the view and also a leading and trailing.
Then make an outlet for the height constraint. In the viewDidAppear method you should wright the below code:
heightConstraint.constant = myView.frame.size.width

Related

StackView not appearing correct on all screen sizes

I have a ViewController that contains a Stack View. In this Stack View there are 3 more Stack Views. The first contains 3 labels, the second contains more Stack Views with buttons and labels, and the third contains 2 buttons and a label. And at the bottom, there is a button. The layout is fine on screen sizes from 4,7" and bigger. But when the screen size is smaller, it cuts out the top Stack View. I have tried to set constraints on leading, trailing, top and bottom in different variations (with and without top and bottom constraints) But I can't make it work properly. I have attached screenshots of the different screen types.
EDIT* Depending on the selection from the previous ViewController, the middle Stack View(the one with the check boxes) can be isHidden When its hidden, the view is correct.
Generally you don't set height on UIStackView. They are dependent on it's content. This will cause your stackview to get out of the screen height. Have you used the view hierarchy? If you want to cover the small sized phones you could put your main stackView inside a scrollView to still be able to see all content.
It's a bit difficult to diagnose what's happening without seeing the constraints you apply to the views, however I'll recommend you some things that may help:
Set the space between views using size classes so you can set the right one depending on the screen size and avoid the overlap with the below views.
In case you are doing it, don't set a height constraint for any stackView.
To align the top StackView I would use not only a top constraint to the top bar (of type greater than or equal) but also a vertical center constraint with a right multiplier (with a high priority). In this way you ensure the top stack view is aligned vertically in proportion to the screen size and with the top constraint you ensure the stackView doesn't hide below the top bar.
Make sure you are hiding the right stackView.

How to set constraints to multiple UIImageView's in Swift

After hours of attempting to find a solution, as well as trying and failing myself I decided to ask here.
As shown on the picture below I have 15 Image views in a pyramid shape that I would like to set constraints on.
I have tried to:
Constraint equal width and height on all images
Constraint center image on line 1, 3 and 5 to horizontal center
Align vertical centers to all images on each line
Etc etc
The result is always the image view going out of bounds or similar issues. (Clip to Bounds is true)
Anyone have a solution or suggestions?
try putting them all in stack views then putting all those stack views inside a stack view and putting constraints on that
like this take a look at the view hierarchy on the left
to get the spacing i achieved just adjust the spacing on the right inside the attributes inspector
and its even able to have constraints on the highest stack view
all the errors go away once you add constraints to the top stack view
like shown here
Embed all your imageViews in a UIView.
set the top, bottom, leading and trailing constraint inside that view (top image to the superview, etc.).
align the UIView horizontally and vertically in the container.
You probably also want to set a width to your UIView, but I let you think about the final result you want.

How to preserve constraints for hidden views within UIStackView

I have three buttons within a horizontal stack view and I have set the autolayout up so they appear based on certain criteria.
For example, first button will be 40% of the stack view width, second button has the same width as the first button, and third button takes the remaining width. Height of the buttons are the same as the stack view. They are all spaced equally, 8 points apart. Stack view's distribution is set to to "equal spacing" and alignment is set to "center".
The issue appears when I decide to hide the first two buttons, but still would like the third button to appear in the same spot with the same width. Autolayout would resize the third button as if the first button and second button are not there.
How do I make it so the autolayout created continues to be preserved as if the hidden buttons are still there?
Couldn't you just set the alpha to 0 and userInteractionEnabled to NO for the buttons you want to "hide"? This would cause them to disappear, and I don't think that it will cause the third button to expand.
Use a second constraint to the container that can act as a backup constraint. Or just re-recreate the desired constraint via code.
I have one more better solution. Add the three UIView in stack align as per your need, then add the button in every UIView. Now you can play with button hidden true/false, here UIView will always be with clear color. Alignment won't change.

Changing which view stretches when using auto layout and pinning

I am updating my app to handle the iPhone 5 layout. I have a view that has a variety of components.
I am using auto layout and almost have everything setup correctly. My challenge is that I have pinned two views so that they have a vertical spacing of 0. This makes sure that one of the views stretches so that the items stay touching. However, I want the view that is currently stretching to stay in place, and for the other view to stretch and meet at the edges. Does this make any sense? Anyone have any experience with this?
if you want to fix the height of a view put a constraints with the height of the view and the other view will be fixed by bottome end the vertical spacing will be 0 betwwen those views.

AutoLayout: Vertically centering two UIViews in a superview that can resize

I have two UIButtons, one on top of the other, in a superview whose height can be resized. The two buttons should have a constant vertical spacing between them, but the top and bottom spacing should resize so that the two buttons stay centered in the superview as it resizes.
I tried creating two less-than-or-equal constraints (with equal priority) on the spacing to the superview for each button, as well as a constant vertical spacing between the buttons, as shown below:
(The reason why it's less-than-or-equal here is because this view is defined at the given height in IB for 4" screens, but can be shrunk for 3.5" screens.) However, this doesn't do the trick, as you can see from the screenshot while the app is running:
It's almost as if you want to be able to tell AutoLayout that the two constraints themselves should have equal values, even if they are both set to "less-than-or-equal". Is there any way to do what I'm trying to do, or perhaps a better way?
This is so trivial to do in IB.
1) ⌃ drag from button1 to top. select "center horizontally in container".
2) ⌃ drag from button1 to left. select "center vertically in container".
3) do the same with button2.
4) now the only thing left to do is size the buttons because this is what it looks like.
This is also very trivial.
5) ⌃ drag from button1 to the left. select "leading space to container margin".
6) ⌃ drag from button1 to the right. select "trailing space to container margin".
7) do the exact same thing with button2.
The finished product, looks like this (NB I didn't quite center them, but I could have easily enough):
The simplest way to vertically center is to add a NSLayoutAttributeCenterY constraint - preferably to the element that is near the center of the view. And if all views have a vertical spacing constraints, then they will all be centred. No need to muck with the view hierarchy or add spacer views.
[self.view addConstraint:
[NSLayoutConstraint constraintWithItem:button2
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0]];
If you need to adjust the positioning, set the constant. For example: constant:-30 will move it up 30 points.
You can also anchor elements based on different logical areas of the view. For example, if you wanted to anchor your first button at 25% of the view height, you can set the multiplier to 0.5.
Agreed with rdelmar. Here's another option if you want to preserve view hierarchy.
You are currently spacing the buttons at the top and bottom using constraints. Instead, create two empty UIViews, they will be used as spacers. They should be positioned one at the top and one at the bottom of your buttons. Using autolayout constraints, make sure that the height of these two spacer views is always equal. Make sure they are pinned to the top and bottom of the buttons and the top and bottom of the superview, respectively.
In VFL: V:|-[spacer1(==spacer2)]-[button1]-(20)-[button2]-[spacer2(==spacer1)]-|.
You may have to do this in code, I'm not sure if IB can do this.
One way to accomplish this is to enclose the two buttons in another UIView, and center that view in the controller's view. Give the buttons a fixed distance to the top and bottom of this view, and either a fixed distance between them, or a fixed height for the view.