I have in my main view two elements. A Stack View on the top of the frame, and a View at the bottom. Inside the top Stack View I have some labels. One of these two labels I want to have with a fixed distance to the parent container (The Stack View), while the other one I want to the edge. As it is shown here:
I believe the constrains are visible correctly in this image.
Now, the constrain adding 50 units to the lead/trail of the label Foo do not work. The error shown is the following:
For some reason, there is another extra constrain I have not added (The second one in the image) and that one, I cannot delete, but only the one I added (The 50 units). If I apply this suggested change, it looks stretched to the lead/trail, as I want to avoid.
What am I doing wrong? Why this is behaving in such an unpredictable way? What is blocking my label to have a fixed lead/trail to its parent container, the Stack View?
One of these two labels I want to have with a fixed distance to the parent container (The Stack View), while the other one I want to the edge
Okay. So that would not be a stack view! Just put these labels into an ordinary view and configure the constraints.
The reason is that it is the job of a stack view to make constraints. It manufactures a bunch of constraints on the arranged subviews. Therefore you must not apply constraints to those arranged subviews; they will, as you have seen, conflict with what the stack view is doing.
What a stack view does is fixed, and limited. If you don't like what it does, don't use it. Remember, a stack view is not doing anything that you couldn't do yourself by writing the constraints yourself. So just do that.
Related
I have been struggling with getting buttons (circular) to keep their size in a stack view to no avail.I have two rows of buttons where I place each row in its own horizontal stack view and then embed both stack views in an outer stack view to make it easier to set constraints.
The issue is that the buttons do not keep their original size in portrait or landscape. What settings am I missing to achieve this? I set the size of each button to w=50 and h=50 by resizing each button (no constraints)
Before embedding stack view:
Top row in a stack view:
Each button is of Type CircularButton
I set the size of each button to w=50 and h=50 by resizing each button (no constraints)
That is certainly one thing you are doing wrong: "no constraints". The stack view is a constraint maker. That is all it is. But it is not a mind-reader. It needs its arranged views to have certain constraints, under certain configurations, in order to know what you want. You have to tell it. Constraints are how you do that.
Let's stipulate that a lot of your question is a red herring — the roundedness of the buttons, the double set of stack views. All you want to know is how to make three buttons be spaced horizontally at equal distribution by a stack view without losing their size. Here's how.
First, configure your stack view like this:
Second, give your buttons height and width constraints, and wrap them in the stack view. Now use more constraints to position and size the stack view where you want the buttons distributed:
As you can see, that works as desired in the running app:
The rest of your interface merely builds upon that.
In the Attributes Inspector, you can set the alignment and distribution to center. This should work:
Also provide the same height and width for the buttons or put aspect ratio of 1:1 for the buttons.
I'm starting a new project that supports iOS9 upwards and after looking at Apple's constraint guidelines they appear to suggest using StackViews whenever possible. After reading a few articles and the apple documentation I've a basic understanding of how to create them and their benefits but I'm still not sure when not to use them and how to arrange them.
For example in the below view should I use:
One big StackView on a vertical axis that covers the entire super view.
Three StackViews with regular constraints pinning them to each other and the super view.
One big StackView that covers the entire super view with three stack views within that view
No StackViews, this view isn't suitable
In general how do I decide how I layout my stackviews and whether to use them?
I've started to use stack views more and more, especially since Xcode 8.x. Every stack view you add saves you adding some auto layout constraints (3 vertically stacked labels in a view would probably need 9 constraints, that could be just 3 with a stack view)
If all elements are in vertical stack views, it's unlikely you'd need to embed one inside another - you'd usually do that when you have a horizontal one inside a vertical, or vice-versa. So in the example above, I'd start with one large stack view.
In Xcode 7.x there were issues with the intrinsic sizes of UILabels not being calculated correctly. In these cases, you can set a placeholder intrinsic size for each label in the size inspector.
That problem aside, get stacking!
I have a problem and can't see your screenshot but I have some points that help you decide:
Do use stack views for all linear arranged views
I prefer set the root stack view to the size that contains exactly the content without whitespace (so constraint it to be as the superview size only if that's the content size)
The stack view uses auto layout to determine the size of it's subviews, so you should validate that your subviews do tell their best suitable size - maybe by using intrinsicContentSize() [only when needed!] (be careful with it)
you can practice stack views in interface builder, try to change stack view properties, hide subviews (with hidden property), and play with constraints, it's great!
Good luck =]
Have a nice play
I am trying to embed 4 UILabels and a UIView into a stack view. I selected all the labels then click the 'embed in stack' option. This then causes the labels to disappear from the view controller with ridiculous widths and X positions (e.g. one of the labels went from a width of 300 pts to 61,000,000 pts.) All the views I am trying to embed have correct constraints with each other and the rest of the view controller.
I've attached a photo of the views I am trying to embed in a stack (giving them background colours for visibility).
UI elements I want to embed in stack
All the views I am trying to embed have correct constraints with each other
There's your problem (at least in part). Do you understand what a stack view is? It is nothing but a shortcut for making constrains on its embedded views. It is a contraint maker.
For a stack view to work on your labels, therefore, your labels must have no constraints to one another. Rather it is the stack view itself that must be constrained (and the failure to do that sounds like the other half of your problem).
If u have a space when u want to put stackView, first put stackView, add constrains to that stackView and add the subviews on it.
I have a Vertical UIStackView with 7 elements inside. These elements are not collectively tall enough to fill the entire view, so they get spaced based on the distribution value. I would like the arranged views to stack at the top of the view, with no space at the top and empty space at the bottom. I would also like to be able to control the spacing below each view as well, if possible.
I have tried every available distribution option, none of them accomplish what I'm trying to do. Help is appreciated!
Update: Adding an image of my desired result to make it easier to understand
The views have variable heights (no problem, I have this working)
The views should appear in the order I add them (also working)
The functionality I want is this: The first view is anchored to the top of the stack view, the second view is anchored to the bottom of the first view, etc.
Have you tried using a stack view that embeds another stack view and an empty view. This could give you the results that you require. Create your view hierarchy this way.
Stackview
Stackview
FirstView
SecondView
ThirdView
....
SeventhView
PaddingView
By embedding your 7 views inside a stack view and then use a padding view and then embed the first stack view and the padding view inside another stack view you could achieve all the things that you want.
This is what I'm trying to do...
I have one view controller that needs to dynamically display different subviews based on the presence of some data.
Here is a simple mockup. Each colored block represents a unique subview.
Sometimes the green block needs to be at the top, sometimes the green block won't display at all, sometimes the light blue block will be something different, etc.
Each subview has interactive elements, so I've been creating and adding them like so:
Defining a new view controller
Defining its view
Calling addChildViewController and didMoveToParentViewController
Calling addSubview on myNewViewController.view
Using SnapKit to make auto layout constraints to position the view
I want to transition to UIStackView because it seems a good support system for this view because all I need to do is stack its subviews. I'm seeing many conflicting constraint errors and unexpected view frames when trying to add subviews with their own inner auto layout constraints.
Question
Am I setting myself up for failure here by embedding the views of 4-6 view controllers in the view of one view controller?
Also, how do I give the added views properties like minimum heights or content sizes without seeing many breaking constraints with UIStackView? (So they can stack, but one of them is say, 400 tall, and the other is 200 tall)
Answer
You can absolutely do this using UIContainerViews combined with UIStackViews and UIScrollViews, it's a complicated setup so here's a starter project to get you started:
https://github.com/Rnorback/ScrollingStackView
Here's what that project looks like:
You want the containers to have different sizes. In order to do that, simply add height constraints to the containers with Autolayout. If you want to change the height of the scrolling. Then you'll need to change the height constraint of the UIStackView.
Brief Explanation
When creating this setup, you have to make sure the UIStackView distribution setting stays in fill. That way you can set height constraints on UIContainerViews.
When setting up anything in a UIScrollView you have to make sure that the object is pinned to the edges of the scroll view and has a defined width and height, otherwise the scrollview will throw a constriant error. I think of it like the scrollview tries to press in on all sides of your content view and if any side gives, the scrollview won't be able to present it properly.
Hope this helps.