Is there a way to define a min/max height of UI element with FluentLayout?
My situation is like this:
Black UIView must be atleast 50px high. If anyone of it's child controls (Red UIView or BigTextUILabel) exceedes that 50px - it must stretch to accomodate its content.
If I define constraints:
blackView.Above(Table),
blackView.Height().GreaterThanOrEqualTo(50),
blackView.Height().GreaterThanOrEqualTo().HeightOf(redView)
blackView will stretch over whole screen (if table is empty). On the other hand if I change constraints:
blackView.Above(Table),
blackView.Height().GreaterThanOrEqualTo(50),
blackView.Height().EqualTo().HeightOf(redView)
redView will be stretched so the height of the red wiew (in this example) is equal to the height of the black view. So the First and Second UILabels wont be in the center of black UIView.
I couldn't find any examples on Priority or FullHeightOf. So to tell you the truth I don't know how it works.
Related
I'm struggling a bit with the auto layout constraints in a super simple test view.
For test I added a label, want it x number of pixels from left side, and 5 pixels from top, right, bottom.
When I do this and do an update frame, the view collapse to the min height, and when I insert the view into a tab, the main window collapses and I cannot resize the height.
I can understand why the view collapses to min height, but why does the main window collapse, and why can't I adjust the height.
Which is the missing / wrong constraints.
Thanks
Edit: Noticed I by mistake used a TextField instead of a Label which could have explained the fixed height, but even after changing to a label I see the same issue. If I instead set the height to fixed, so the constraints are left, top, right, height, then I can resize the window as expected, but obviously the label doesn't resize its height.
The label's content-hugging priorities are presumably greater than NSLayoutPriorityWindowSizeStayPut (500). That tells the auto layout system to prefer to resize the window rather than stretch the label beyond the size required by its contents.
Reduce that priority.
I need to autolayout a storyboard UIView with a single UIControl. The UIControl should be centered, needs to have a aspect ratio of 1:1 and should always use 90% of the superviews width or height depending on the device orientation without clipping.
I added 4 constraints
Center Y Alignment - View - Superview
Center X Alignment - View - Superview
Equal Widths - View - Superview with multiplier set to 0.9
Aspect Ratio - View - View with multiplier set to 1:1
This setup works fine in portrait mode but fails in landscape mode. (See pictures below)
What kind of constraint do i need to solve this problem. Do i have to change the constraints if the device is rotated?
Portrait mode
Landscape mode - wrong
Landscape mode - mockup. Thats what i want.
Here is a way to do it:
Start with the four constraints you list above: Center X, Center Y, Equal Widths (0.9 multiplier), and Aspect Ratio, all with priority 1000.
Change the priority of the Equal Widths to 750. This will allow Auto Layout to ignore or modify this constraint if necessary.
Add an Equal Heights (View - Superview) constraint, but instead of Equal, make it Less Than or Equal with a multiplier of 0.9. Leave its priority at 1000.
Now, when you are in portrait, Auto Layout will be able to satisfy all of your constraints by making the width of the red box to be 90% as before. When you switch to landscape, the Equal Heights constraint will ensure that the red box doesn't grow beyond 90% of the height since this constraint has a 1000 priority, but Auto Layout will also make the box as big as possible in an attempt to best serve the Equal Widths constraint.
You forced your view width and your aspect ratio. So when you width grows, autolayout will force your height to grow up too to keep a 1:1 aspect ratio.
You have to:
Set constraints for your height and width to be <= 0.9* Superview with a 1000 priority
Set constraints for your height and width to be == 0.9* Superview with a 750 priority
I didn't try, but it should look better ;)
I have a view in which I placed a scrollView that fits the entire view. Inside the scrollView I have a textView, below a imageView, below a textView and so on. The textViews are filled with content from the ViewController with localized text, so its height will change depending on language. I gave the textViews the constraints for top, bottom, left and right with 10 each. The ImageViews i gave the constraints top and bottom with 10 each, width 200 and centered in container horizontal. The height of the images is different for each image and no constraint for the height is given.
The first result was, the scrollView got a width of the longest text of the localized text. I changed for the
scrollView
Content Hugging Priority Horizontal to 995 and Vertical to 250.
textViews
Content Hugging Priority Horizontal of 400 and 200 Vertical,
Content Compression Resistance Priority Horizontal is 200 and Vertical 750.
Perfect result in portrait mode. When changing to landscape the width of the scrollView stays at 320 and is aligned to the left.
How can I fix the problem to let the scrollView take 100% width of the screen without giving the textViews the chance to force to enlarge themselves to 100% width?
Found solution:
The scrollView has constraints: top/bottom 8 and left/right 0 each to superview.
The textViews have constraints to top, left, bottom and right.
The images have constraints top, bottom and width, centered to X in container.
This results that the textViews take one line and grow to giant width.
Then I centered the textViews to X in Container and selected all textViews and images and centered them too.
Now the scrollView takes 100% width of screen, height as needed no matter if portrait or landscape.
So for all who have maybe the same issue: scrollView looks a bit smaller than the view, its constraints when adding are 0 to left and right and a top/bottom >0. When drag and drop scrollView in the view it takes 100% of the view size. That was the problem, the constraints were -16. Setting the scrollView to x = 16 and width = 288 results in fitting properly to the view! Next giving the textViews constraints top/left/bottom/right and center it to container (even if offset to real center, right to the item is 0 predefined - change it to use current canvas value).
Is it possible to have an NSView autosize (vertically) to fit its contents? The contents are just two NSTextFields, one (on top of the view) that's always the same height and the other (near the bottom of the view) that's of a variable height.
Something that could make it more difficult is that the NSView is an NSCollectionViewItem's view.
The problem is that the width needs to be known before the height can be calculated. A successful implementation requires two layout loops. The first determines the width. That width is then taken and the height is calculated. A constraint is then added or modified to reflect the height and layout must happen again.
To achieve this, I subclassed the view to store a copy of the frame size locally. When the contents of the view changed, I would clear the width to zero. If the actual frame rectangle width was discovered to be different than the stored width after layout, then I knew that height needed calculated and another layout needed to be executed in the event that the width change caused a height change.
I am now quite comfortable using autosizing masks in IB but there are two autosizing setting that I am not clear how they are intended to differ:
Setting 1
Autosizing with both upper and lower anchors http://dl.dropbox.com/u/11270323/stackoverflow/autosize-mask-0.png
Setting 2
Autosizing with only uppper anchor http://dl.dropbox.com/u/11270323/stackoverflow/autosize-mask-1.png
Some context. The UIView subclass that uses these settings is a child subview. Setting 1 is giving me the behavior I want - subview expands/contracts with its parent view - while setting 2 is slightly different in a non-obvious way.
What is the intended layout difference between these two settings?
Thanks,
Doug
Setting 1:
The view will resize vertically so that both the distance from the top of the superview and the distance from the bottom of the superview are preserved. Basically, the view will grow and shrink in tandem with the superview; if the superview gets taller by 30 pixels, so will this view.
Setting 2:
The view will resize vertically so that the distance from the top of the superview is preserved, and the proportional height of the view is preserved. Basically, the view will grow proportionally with the the superview; if the superview gets taller by 10%, this view will also get taller by 10%.
Note how these differ in practice. Assume the superview is 100px tall, and the subview is 60px tall, with a 20px buffer on the top and bottom. Now let's resize the superview to 150px tall.
Setting 1: The subview grows to preserve the 20px margins, becoming 110px tall.
Setting 2: The subview grows by 50% (60px -> 90px). The top margin is still 20px, but the bottom margin is now 40px.
In general, you usually want the behavior in Setting 1. You might use Setting 2 if you had a master/detail view split top/bottom, and you wanted both sections to grow proportionally with the superview. In that case, you would give both views flexible height, fixing the top margin of the top view and the bottom margin of the bottom view.
BJ's answer is really awesome. But I think his example is incorrect.
Assume the superview is 100px tall, and the subview is 60px tall, with
a 20px buffer on the top and bottom. Now let's resize the superview to
150px tall.
So for Setting 2, the top margin is undoubtedly still 20px, but the subview and the bottom margin should both grow by (150 - 20) / (100 - 20) = 62.5%. The subview height becomes 97.5px, and the bottom margin is now 32.5px.
In other words, the proportion of the subview height to the bottom margin should be preserved in this case.