IOS/Storyboard/Autolayout. Center horizontal group of elements - ios

Using autolayout in Storyboard, is there a straightforward way to center a group of elements without making them part of a subview?
For example if I have one label 50 and a second element Points, is there a way to hold them together as one and then center it.
Right now, I am able to hold the space between them constant (as it needs to be) and horizontally align but I can't get the two of them together centered. My approach has been to set a leading space before the first element and a trailing space after the second element, but something is throwing it off. I know I could combine them into one label and center it, but I'm looking for a solution that I can reuse every time I have one of these all too common situations.
Thanks for any suggestions.
Image:
Storyboard.

This scenario is very common and very simple to solve: just get rid of the leading and trailing constraints and instead add horizontalCenter to the first label regarding the view. After that all you gotta do is adding horizontalCenter to the second one regarding the first and you're set! Now both of them are linked together and well centered.
If you need more help with this, just share your repo and I'll fork it.

I know your question specified that you don't want to make the two labels part of a subview, but I'm not aware of a good way to do that and thought I would at least mention that the standard / recommended way to handle this situation would be to add "3K" and "Points" to a horizontal stack view, and then horizontally center the stack view and vertically constrain it to "Explorer" above.
This would ultimately require the same or less constraints as what you have now because you wouldn't need to create constraints for the labels inside the stack view.
See Apple references here:
https://developer.apple.com/videos/play/wwdc2015/218/?time=134
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/LayoutUsingStackViews.html

Related

Constraints with static cell are ambiguous

I'm having some problems with properly setting up my static cell the way I want it while making it look good for different screen sizes.
Somehow I don't seem to get how constraints are supposed to work.
One of my views contains a UIViewController with a table view. However, if I change my preview device in the storyboard to, say, an iPad, the table view doesn't get resized. Am I supposed to handle stuff like this from code only or is there a way to handle this from the storyboard (like setting width and height to always fill)?
I'm trying to set up a static cell so it looks good on devices with different screen sizes. Things work well enough when I have only two elements (e.g. one label left and one label right - just like in the standard template), but as soon as I add more things, I'm running into a lot of warnings, e.g. that width and height are ambiguous.
To me, it seems like I'm missing some key concept of constraints.
Look at the picture provided. What I want is the following:
Date to be a certain distance away from my left table border
The Stack View of volume + pic in centered in the middle
pic & price & label (there is one more for the measurement) to be represent the right label
I'm unable to actually try this at the moment but here's the path I would go.
Date:
Fixed Top, Bottom, & Leading to Container constraints to 8 (or whatever you'd like).
Volume Stack
Fixed Top & Bottom to Container constraints to 8.
Price Stack
Fixed Top, Bottom, & Trailing to Container constraints to 8.
You'll have some overlap issues with smaller screens at this point. You should get the "Red Circle" to suggest which constraints to add. Click and read each one and it will be specific enough to walk you through which you want resizing, resetting priority, etc.
*I hate dealing with constraints.
Good luck! I'll try tonight to see if I gave an acceptable answer. :)

Xcode/Stackview, empty labels freaks out in stack view?

hopefully an easy one here. I have some labels and text fields. Between them, I want some empty labels, which will if needed to be error texts. But when I try to stack view it all, Xcode zooms out and nothing can be seen on the viewController.
Anything else I need to change for it to work?
You can see a picture of it here before I hit stack view:
The email label and text field are already in stack view, so are passwords, gentag passwords and label/button.
This certainly appears to be a bug. I duplicated your issue. I was able to solve it by setting a height/width to each empty spacer label, prior to adding it to my stack view. This doesn't make sense because when you add an object to a stack view it loses all of the constraints it has. None the less it resolved the issue:
Sounds like its just an auto layout issue (or lack of). Can be really messy, best to just keep playing around.
As you've already done, I would first put each label and its text field in a horizontal stack view and add constraints.
Then I'd add each of these stackviews to their individual warning labels in a vertical stackview and add constraints.
Finally I would combine all of the stackviews into one vertical stackview!

Autolayout vertical spacing of group of textlabels when one is empty

I have a group of text labels that are vertically spaced to each other 15 pixels.
The problem is that when one of the labels is empty, then there is extra space between the other two labels above and below the empty one (30 pixels).
I know that one solution would be to constraint all the text labels to the top and to the labels above and then I can just delete it and everything should look aligned but the problem is that I reuse the view and sometimes all the labels have text and sometimes some are empty. So if I delete the label, I would have to recreate it and readjust the constraints manually.
Is there a way to delete the extra vertical spacing when one of the labels is empty without deleting it?
Edit 1: The labels don't have any Height constraint so the empty one will be 0 pixels high
Edit 2: I need to support iOS7+
Possible options:
do not use multiple labels, but a single one, possibly using an attributed string if you need different formatting for the different parts
add an outlet to each of your constraints, and adjust the constant based on the label having text or not
There are quite a few others, including the use of table views, stack views (iOS 9+), and probably more...
If you are ok with supporting iOS 9 and above then you can use stack view and set the constraints for the labels within the stack view. But instead of emptying the label you should hide the label. When the label is hidden the stack view automatically brings up all the labels below it. You should get the desired behaviour using this method.
My rule of thumb is if layouts get overly complicated to do in Interface Builder, then it's better to just write code to do it. In this case I'm not even sure it's possible to define in IB. But even if it was, I'd do it in code. It's not a complicated layout, it will be more reusable, it will be cleaner in code.
A few options:
A - You could modify constraints in viewWillLayoutSubviews - it's kinda messy to hold on to so many top constraints. Somewhat less messy if you add them all to an outlet collection (array of outlets, basically).
B - You could manually adjust frames in viewDidLayoutSubviews - although it then begs the question, why even use AutoLayout at all if you're doing almost all the work manually anyway.
C - Use SnapKit and generate those constraints in viewDidLoad and / or update them whenever the text changes. I highly recommend SnapKit. Think of it as a sane way of programmatically creating AutoLayout constraints. It's very clean, and very simple.
See http://snapkit.io

Complex AutoLayout for Cell with dynamic size

I have a cell that contains a container with 10 subviews (two of them are simply bounds and the others are labels). The scheme looks like this.
Dynamic labels may contain huge text so the cells should conform the appropriate size to fit the content. The question is how to set up all the constraints manually... I've tried a dozen of times to do it myself but seems I'm not that good at this. The table view supports auto dimension for row height and uses custom estimated height.
In Storyboard it looks this way.
Where blue views are a subviews of View C. A grey view behind is a View B. Bold labels are static and the others are dynamic.
Demo project.
How to setup constraints?
Thank you very much in advance!
I managed to setup your constraints so that you get the result you needed. This is what I get:
I hope this is how you wanted it to look like.
Here is a link with the project.
I will try to explain how I added the constraints so that it makes more sense.
First of all, you have view B which needs to be as big as the contentView. For this you add top/bottom/left/right constraints to the superView. Because you are using automatic dimensions, if you add all constraints with priority 1000(the maximum one), you will get some error with the constraints while running. This is because, before the cell size can be calculated automatically it is zero, so the constraints crash. Therefore, I set the priority for top and trailing space with a priority of 999 so that you don't see the error log anymore. The result is the same.
Then views C needs (top or bottom)/left/right and height constraint
Then you need to add the constraints for the labels. Since you need the right ones to have multiple lines, the constraints need to specify the vertical layout for this particular case. So, you have as follows: first label: top/left to name label and right to super view. All the other have top to the previous one,and bottom to the next one.
for the labels that don't need to resize you just need leading space to parent,horizontal space to the right label and static width. Also, you will need a constraint to align the top with the label on the right.
This is the result I get:
Hope my explanation made sense, just let me know if you have questions. Good luck with your project!

Very basic AutoLayout

In a View Controller I have two UILabels.
I'm trying to start to understand the AutoLayout feature, but I'm finding tutorials using storyboards, complex layouts, scrollViews and other components that are absolutely more complex of what I'm trying to achieve and understand.
This is my very basic setup:
What I simply want - to start to dive in the subject - is:
have the distance between the two labels preserved when testing it on 3.5' and 4' screens
have the bottom and top margin of both the labels to be proportionally preserved when testing it on 3.5' and 4' screens. EDIT: please consider that the desired position it's not the exact center
I have tried to add constraints via the "Pin" option, but with no success at all. Maybe I should put them inside another view to act as a container?
This is a very easy question, but right now this AutoLayout feature is really confusing me. And maybe this can be a good starting point to understand what right now looks to me to be designed by a crazy scientist :)
Put both UILabels in a containerView, and align containerView vertically center.
I would support #RoboticCat for the statement he made. But I would try to deliver what I learned from those videos.
For first requirement:
Ctrl+click on any of the label & drag n drop it on another label. Select "Vertical spacing" option from the popup. this will full fill your first requirement.
For second one:
Ctrl+click on top label & drag n drop it on view of viewController. select "Top space..." option from popup.
repeat previous step between bottom label & view. This time select "Bottom space.. " option from popup.
Now navigate to Size Inspector of each label. There you can find the constraints just created. Click them to perform Edit.
Decrease priority of top & bottom constraints to 500 from concerned labels. This will solve your issue.
Let me know if more info needed.. :)

Resources