How to disable stackview autosize - ios

So I have three text fields inside a horizontal stackview that are like this:
I've made this by placing a placeholder text and selected Fill Porportionally from the Stack View menu.
However, I would really love to stick with this ratio but everytime I type something long, the text fields increase automatically. Is there anyway to disable auto sizing so that I can keep these initial ratio at all times?
Note: second and third text fields are not the same size
Thanks!!
Edit: Bump.. ='(

Just add width constraints to the views, setting them to the widths you want. Or set constraints between the views to control their proportions directly.
Your view widths seem to be 272, 135, and 168. So create an equal-width constraint between the left and middle views, then edit the constraint to set its multiplier to 272:135. Then create an equal-width constraint between the left and the right views and set its multiplier to 272:168.

Related

Design UIView so that it can dynamically change its height based on the content height

In a XIB file I have a CustomView related to a class with the same name.
The view content is quite simple.
There are a vertical stackview and inside the stackview there are two labels. The stackview is vertically aligned to the view that contains it:
The first label (title) contains a static text (always a few characters).
The second label (subtitle) can have variable length text.
I add this CustomView with other similar views as a subview of a Content View, as it was a “row”.
for i in 0...aViews.count {
var v = CustomView(frame: CGRect(x: 0, y: _y, width: 320, height: 100))
v.labelText = "my long label text ..."
contentView.addSubview(v)
// ...
}
As you can imagine, the title label should have a fixed position (top and left), that is, there cannot be a row with the title starting at 10 points and another at 14.
I must admit I naively thought the position of the label would have been automatically managed by the same fact that I aligned vertically the stackview. I was wrong and I noticed no problem at all, until they told me the second label, the subtitle, could contain more than one line.
I added lines to the label directly in the storyboard, and found out that:
the container of the stackview doesn’t change its height based on the height of its content;
the position of the “fixed” elements is maybe vertically centered but not fixed;
What I need is the following:
the labels should be “grouped” and aligned vertically: there should be the same amount of space from the top of the first label to the upper border of the container and from the bottom of the second label to the bottom border;
when the second label has to display more than one line, the container view should change its height accordingly;
Is this possible? How should I design my view?
OK - looking at your project, you're not far off... just a couple key items.
In your CustomView.xib, you had no constraint between Fixed Label and Date Label. The result is that the Date Label grows up from the bottom of the view, with nothing to stop it.
Also in your CustomView.xib, you had the Fixed Label constrained to the trailing edge... I assume you want it left-aligned with Date Label
When creating your CustomViews, you were setting a height constraint of 100 -- which defeats the purpose of allowing the content to determine the size.
In CustomView class, you had contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] commented out. That line should be there.
In your view controller, you added a height constraint to contentView with a low priority. Best option is to make that a Placeholder constraint (double-click the constraint, and select the Placeholder checkbox). That way the constraint is removed at run-time, but is there during design (and Storyboard doesn't complain).
You were doing a few other un-necessary things - likely you were trying different stuff to get it to work.
The view setup (adding your views) is best done in viewDidLoad() -- definitely not in viewDidLayoutSubviews()
I'm guessing that, in your CustomView, instead of an explicit width of 200 you probably want to constrain the Date Label leading and trailing, allowing it to horizontally stretch based on the device width... but I left it at 200.
If you can follow that information, you should be able to fix the issue(s). But, I put the project up as a GitHub repo for you, so you can get it in a "working" state, and so you can see the changes.
Here's the link to the repo: https://github.com/DonMag/ATester2
Here is the result:
And scrolled up a bit:
I think you are mixing absolute positioning of outer views (i.e. manually setting frames) and using autolayout constraints for their inner components, and wrongly expect the dynamic autolayout part to somehow "reach all the way up" to the outer views. For autolayout to do that, you'll need to use autolayout all the way up, including the way CustomViews are positioned in your contentView.
If for whatever reason you do not want to use a TableView or CollectionView for this you could also, for example, try adding your CustomViews as arranged subviews to a vertical stackview that has top/bottom/leading/trailing constraints to contentView, then replace the "Align Center Y" constraint of your CustomView with "Align Top" and "Align Bottom" constraints to actually allow your labels to "push" from the inside if they need more vertical space.
Edit here's a quick sketch to illustrate that setup:
Edit 2 here are a couple of screenshots to clarify further. With a basic layout like this:
the result will look like this at runtime:
Note that the UIStackViews use the "Equal Spacing" Distribution in this example. If you want to create and add your CustomViews programmatically, use the StackView's func addArrangedSubview(_ view: UIView).
Good luck!

Adding Size Constraints for Views inside a UIStackView

I currently have a UIStackView that I add views to, it fits a maximum of 10 views along with a button. The issue however, is that although the views I add are equal size, the button is not.
I have tried adding a constraint that determines sets the button's equal to 1/11th of the StackViewSize (so that all of the views can fit equally), but it just seems to break all the other constraints.
How can I give the button size without breaking a million constraints?
Currently the height of the button is adjusted with each new view added, but that's just ugly.
First of all, set height and width to that button according to your requirement using AutoLayout. Then select your stack view from the Document Outline(in your view controllers hierarchy) & then in Attribute Inspector set its Distribution to 'Fill Proportionally'. Add some spacing if you want.

How to use auto layout to resize views in a table view cell?

I have a cell in which I place four buttons and four labels. Each button gets assigned a picture with width 50 and height 50. Furthermore, all buttons have a corresponding label describing what they're intended for.
My objective is to have the buttons and labels resize to keep the buttons' and labels' aspect ration intact while the screen dimension changes on different devices. I have been playing with auto layout changing the hugging and compression to achieve this but haven't been successful yet. Any help would be much appreciated...
I think you should take a look at a UIStackView, because this seems exactly as a use case for stack. Just put each pair button/label in a stack, and then all four pairs into a horizontal stack, which you constraint to the cell itself. You should be able to handle all you need just by configuring the stack’s properties (axis, distribution, alignment, spacing).
Embed your button and label into a view. Set the width of this view equal widths to content view and change the multiplier value to 1:4. This will adjust the widths of the views according to superview. Also, set the top and bottom constraint to 0 for this view.
Provide center align y-axis constraint to button after setting the width and height constraint to 50. Set its top constraint to a value you deem fit.
Set labels's leading and trailing constraint to a value like 8. Choose center alignment for text. Also, provide top constraint to buttona nd bottom to its superview.
Copy the view and paste to create the three views and provide them equal widths constraint to the first view. Also, provide their leading, trailing, top and bottom constraints.
Here are a fast tutorial in how to achieve that:
1-
2- completion of the first Gif:
Note you can achieve the same output using a UIStackView

Center multiple UILabels on a line

I want to horizontally center multiple UILabels - as a group - on a line in Interface Builder. One the straight view controller i could not figure out how to do this. I read comments about place the UILabels in a View and then centering the view in the view controller. When I tried this, overtime I said to update frames in the interface builder, the View would be resized down to nothing. (i.e. its height and width would be set to 0 by IB). I need to know how to get this to work in interface builder.
An example of a line containing multiple labels I want horizontally centered is below. The braces simply indicate the start and end of each label and are not art of the text. The <- 6 -> is meant to indicate the trailing space from label 1 to label 2 is 6
Label 1 Label 2
[Rating: 0.0]<- 6 ->[Distance: 125.34 Kilometers]
Any suggestions would be greatly appreciated.
Here is an EXACT example of what I have done and it does not work:
Create a new view controller in IB
Place a page label at the top of the page centered horizontally and aligned to the top of the layout guide.
Add a view with the following constraints on the page:
Now add two labels to the view with the following constraints:
Once this is done I get the following error and updating the frames will cause it to be give a height and width of 0
Here is what the page looks like in IB:
I need the height and width of the view to size automatically so that I have put a multiline label in the view and have all the contents of the view treated as a group and centered on the page.
Any suggestions would be greatly appreciated.
Here is a snapshot of a working set of all the constraints on an abbreviated layout that produces an always-centered view that automatically resizes with the child views (i.e., as the content of any label changes, the view grows or shrinks around it).
Important to your solution, the view has neither a height nor width constraint; its size is constrained entirely by its descendant constraints.
The key is that every component has a direct or indirect constraint from which its size and position are specified or can be inferred. For example, in order for the view to infer its width, the child labels must have a leading space constraint on the first label, a trailing space constraint on the last label, and a horizontal space constraint between interior labels. Those constraints plus the contents of the labels allow the width of the view to be inferred ... and force the view to dynamically conform to that width.
The same applies for the view's height. For example, you can specify the top and bottom space of just one label, or all of them. If just one, the remaining labels can be vertically aligned with it (see "Align Center Y to: Label1" in the screenshot).

How to change uiview's height using auto layout?

So I created this scenario in order to understand how views increase in height according to their content. However am still not able to make it happen.
This is what I have now:
the textview is growing according to content. however the uiview containing it is disappearing. what constraints should I use so that when the uitextview becomes bigger, its parent view also increase in height?
Start by clearing all your constraints from everything so we have a fresh slate.
Step 1: Build your view hierarchy. In this example, we want something like this:
The view controller's view, which we'll call parentView has a subview, which we'll call redView. That redView has a child, a Text Field, which we'll call textField.
The hierarchy looks like this:
Step 2: Set any constraints that are specific to any individual view. In this case, we probably only want to set a width constraint on our text view. For now, I'll just set a width of 200pts.
Step 3: Set the constraints between textView and its parent, redView. Let's say we want a 10pt border all the way around. Let's add these constraints:
Once we've added these constraints we'll gets some auto layout warnings and errors. For starters, because the constraints I added for with and space to superview don't match the actual sizes, I'll get some warnings like this:
There will also be some errors describing missing X and Y positions for redView and for textView. There are really twice as many errors here as necessary. textView knows where to position itself relative to redView. We don't need more constraints to sort out textView's position. However, redView doesn't know where to position itself yet... and so ultimately, textView also sort of doesn't exactly know.
We can update the textView's frame to get rid of the warnings, but let's go ahead and fix the actual errors.
Step 5: Set up redView's constraints relative to the superView. redView already know what size to be. Notice we had no errors for redView's width. It just doesn't know where to be. In this case, I'll go simple and say we want redView to be centered. So we'll want to add these constraints:
Now we've fixed some of the problems. The only problem that remains is the height for everything.
To fix this, we must set the content sizing priorities of textView. Set these all to 1000 and change the "Intrinsic Size" property to "Placeholder".
By now, all of the auto layout errors should be gone and we should only be left with warnings because our storyboard frames don't match what our constraints say they should.
We can fix that by selecting parentView and updating all the frames:
There's one final caveat to this auto layout puzzle when it comes to autosizing based on content size: what happens if our text view has no content?
If our textview has no content, auto layout will choose a height of 0, and our users won't even be able to see that there's a text view there, much less tap in it to add content (and make it expand). When using auto layout and content-based sizing, we should almost always be sure that we've set either an explicit or minimum size for the content view.
We don't have to worry about our textView's width, as we set this explicitly to 200. So let's add a minimum height constraint. Start by adding any height constraint:
Now go to the size inspector for the textView, find this height constraint we added, and edit it into a greater than or equal to constraint:
Storyboard won't reflect the change in content in our textView and resize it appropriately, but your constraints are now set up correctly and this will behave appropriately on your device or in the simulator.
ON UITextView make your you unselected These
Scrolling Enabled
Bounces
Bounce Horizontally
Bounce Vertically
Shows Horizontal Indicator
Shows vertical indicator
Now Change your auto layout constraints like this.
On the Storyboard Page, click on your textview.
Then click on the small triangular in the lower right corner.
Click first on "Clear Constraints".
An then on "Add Missing Constraints".
Its the easiest way.

Resources