Center Label vertically between two UIButton's - swift

everybody some I'm having some trouble vertically centering the or label between the Sign in with apple button and also the login button. Keep in mind that I am creating the SIWA button programmatically and setting the constraints that way also. I have tried getting the origin y coordinate for both buttons, dividing them by 2 and then setting the vertical constraint from the login button to the or label to be (loginButton.frame.origin.y - (divided by 2 value)) but that doesn't seem to work. Thanks for your help.

There's a couple ways to solve this:
Put the 2 buttons and the label in a vertical UIStackview with distribution set to equal spacing. Stackviews are very flexible too, especially in more complex layouts.
Create an empty UIView that sits between the two buttons, then add the label as a subview and center it. Alternatively, you can create 2 spacer views with equal height constraints above and below the label:
V:|[Button][space][Label][spacer2(==spacer1)][Button2]|

Very easy approach: by default, UILabel centers its text vertically in its frame.
So,
constrain the Top of the Label to the Bottom of the top button
constrain the Bottom of the Label to the Top of the bottom button
All done :)

Related

Specify different spacing between arrangedSubviews of stackview

I have my login view designed with stackview. The stackview has five views(segmented control, two textfields, and two buttons)
I set the alignment as Fill and distribution to be Fill proportionally. However, I can not change the spacing between the subViews.
Right now the spacing is 10 but I want 20 spacing between the segmented control and the first textField and 5 spacing between the "Sign In" button and the "Forgot Password?" button.
I know I can just remove the stackviews and use auto layout to achieve my desired positioning but I want to use stackview to control the views during the rotations.
Can anyone please help me with this.
UIStackView has an instance method that applies custom spacing after the specified view.
func setCustomSpacing(_ spacing: CGFloat,
after arrangedSubview: UIView)
stackView.setCustomSpacing(20, after: segmenteControl)
Well what you can do is to add cushion view in stackView to get more space between two views ... clear that cushion view background color and fix its height accoeding to your. demand

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.

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.