Interface Builder - Constraint maximum width and margins - ios

I have a constraint error,
What I want to do is "center the view, have 20 margin on the view, and have a maximum width of 320"
So that on iPad the view is not stretched, but on smaller devices the view can be less than 320 width, and have 20 pts of margin.
However using these rules gives me an error, probably because I say that margins can be >= 20, and width <= 320, and view has no idea how to match that.
I tried using priority but I'm not sure how it works, and I couldn't get anything.
How can I achieve the desired effect using only one view and its constraints?

As you have deduced, autolayout needs to know which constraint it should break in the event of a conflict, and this is done by priorities. However, you have another conflict since the leading/trailing and width constraints are all relative. This means that autolayout cannot determine the view's width.
Change the leading/trailing constraints to = 20 and set their priority to 999 so they can be broken on a wider device. This will allow the width to be determined and eliminate your conflicts.

Like this:
Note that (1) we don't need a trailing margin constraint, as we are already horizontally centered, and (2) the width of 320 has a lowered priority, thus giving the inequality leading margin constraint something to aim at when in doubt but otherwise not interfering.
This is what it looks like on iPhone 4s in Portrait: we are restrained by the side margins:
This is what it looks like on an iPhone 4s in Landscape (and of course on anything wider than that): we expand our width, but only up to 320:

Related

Constraints in Swift not working

I'm trying to add some constraints to my view, but everytime I switch the device, the view goes crazy. How can I fix this?
How I want it to look and how it looks like on the iPhone 8 Plus:
How it looks like when I switch to iPhone SE:
I added these constraints:
0 top
0 left
0 right
686 bottom
If your bottom constraint is larger than the height of the device, naturally, it will be out of bounds.
Moreover, your constraints will be ambiguous if the screen's height is smaller than 686.
You'll need to have a height constraint with a constant of 50 to set up on the view rather than a bottom constraint.
It's not preferable to have such a huge value for any constraint. So when changing devices, the height of screens may change and your constraints will break.
The preferred way will be to create a Height constraint and set it to 686 and don't set the bottom constraint as it's not needed anymore. But the problem can arise here if the screen size is smaller, as the views on the bottom will not be visible. To overcome this you should make use of a scrollview and put this content view inside scroll view.
you can set the Height constraint of View instead of bottom constraint
or
you can use the Size classes

Resizing Auto Layout Constraint

I'm developing an iOS application in Xcode 8. I'm having trouble getting my head around the auto-layout constraints even after reading various tutorials. I am trying to find what combination of constraints allows me to have an adjustable spacing between the top layout guide and the top of my image view.
Below is the preview of the view on iPhone 7 Plus:
iPhone 7 Plus Demo
The top constraint of the UIImageView is currently set to =50, which is the perfect size for larger screens. However, I am trying to have this spacing shrink on smaller screens, as seen below:
iPhone 4s Demo
I have tried what feels like all possible combinations of various constraints with different sizes and priorities but the spacing is either small on all screens or large on all screens. Is there something I am missing?
You can specify different constraint for different trait.
You can do it like below
override var traitCollection: UITraitCollection {
let trait = super.traitCollection
if view.bounds.size.height < 500 {
return UITraitCollection(verticalSizeClass: UIUserInterfaceSizeClass.compact)
}
return trait
}
Override trait collection
Select constraint
Select + button before constant field for the constraint in the inspector
Select height as compact and width as any
It will create another constant field for this constraint.
Specify lower constant value
Else you can make that constraint an outlet and in code, check if view.bounds.size.height < some_value than use smaller value as constant for the constraint else regular value
You can change the top spacing proportional to the height by taking the outlet of the topConstraint and in the viewDidLoad method you can change its value. . Here you need to find a constant value which when multiplied with the actual height of the device gives the required top spacing. Say you need 50p in 7+ which has a screen size of 736p so the constant is 50/736 = 0.067. So in 4s the spacing can be 480 * 0.067 = 33.
You can do this like
topspace.constant = self.view.frame.size.height * 0.067
After some playing around with the above ideas, I found a solution to my problem that lets me see the changes in the storyboard. I position my UIImageView in the preferred location (on iPhone 7+) and set an vertical alignment constraint at the current canvas value - I then set this constraint to have a priority of 750.
I then add a top constraint to the top layout guide which is greater than or equal to 10, this has a priority of 1000.
When seen on a larger screen, the UIImageView positions towards the vertical alignment. When seen on the smaller screens, the vertical alignment pushes the image to the top but the higher priority top constraint of 10 keeps it on the screen.

Xcode Constraints causing image to enlarge to 1920 x 1920

Here's a screenshot of the problem:
How it appears in Xcode:
It's got content compression resistance priority of h:750 v:750, content hugging priority of h:251 v:251, trailing / leading space of 5, width and height equals to 390, top space of 40, and a 1:1 ratio.
EDIT: I'm using Auto-layout.
There are other elements that rely on it, but I'd rather get it displaying properly first.
Here's how it looks like in the iPhone 6 Simulator:
You have too many constraints set which conflict with each other. In particular fixing the width and the leading and trailing at the same time will conflict. So will setting the height and the top/bottom conflict. You are probably getting an error in the console telling you it has had to break some constraints.
If you want the image positioned as per your post and to grow with 1:1 to fill either width or height all you should need is:
Set the leading constraint to 5.
Set the top constraint to 40.
Set the trailing to be >= 5.
Set the bottom to be >= 5.
Set the aspect ration to be 1:1
This is saying that you want the image 40 from the top, and a margin of at least 5 on the right and bottom and an aspect of 1:1. The image view will grow to fit based on the constraint which limits its growth: normally the right in portrait or the bottom in landscape.
You should not set the width or height unless you want to fix or limit it. However if you do that you can not set trailing or bottom.
The image inside will show based on how you have set the image view to present the image: apsect fit, aspect fill etc...
Updated
I just noticed you have the image in a scroll view. I think you need to put the image view in a view which you give a defined size then add that to the scroll view. You may need to do that in code to deal with multiple devices. The scroll view needs to know the content size of the content view. See this tech note: https://developer.apple.com/library/ios/technotes/tn2154/_index.html

iOS auto-layout constraints

I'm unsure of how I should set up some constraints in my auto-layout storyboard in iOS.
I have a textbox and a button next to it, constrained to each other, and they're both constrained to the sides of their superview by 20. It works great for iPhones/iPods. Moving up to iPad, however, the textbox becomes too wide. Is there some way to set a "max width" on the text box in order to allow some growth, and allow the constrains to the superview grow after that point?
It feels like I'm approaching it all wrong, do I have the wrong approach?
The constraint
You can set a constraint for "width less than or equal to X" (whatever your value X is).
Then pair that with your "trailing edge space to the edge of the superview is equal 20".
The Conflict
This will not work as it is though as if the superview is too wide it will create a conflict.
Priorities
What you can do though is give the "edge space" constraint a priority of 1 less than the priority of the width constraint.
So if the width constraint has a priority of 750 (which is default) then give then space constraint a priority of 749.
This has the effect of telling AutoLayout. "If there is a conflict, then break gracefully by 'removing' the space constraint and keeping the width constraint".
You can set a width constraint and in the right side of the screen, instead of equal, select less than or equal (or something like this). This will add a maximum width to your UI element.
You can add width constraint which can be set the constant with the equal value, for example 100 or you can add equal greater than 100 or less equal...
you can use Ctrl+Drag with in a text field to set fix width.

Inequality Constraint Ambiguity

i've a problem in resizing a UIView with Autolayout and constraints.
I'd like to change the origin (less than or equal of original) and the width (greater than or equal of original) but I got this: Inequality Constraint Ambiguity
Do you have idea for solve this?
thanks
I tried to make more than 1 vertical spacing constraint shrink for 3.5" displays, so I had to make 2 constraints between components that I wanted to shrink on smaller screen. One constraint was inequality (greater or equal) where I specified minimum required size, with 1000 priority, other constraint was equality constraint with specific size that is suitable for 4" screen, but with lower priority of 250.
This way Xcode stopped complaining and layout repositioned properly on smaller screen.
Your view is horizontally ambiguous. You do not have enough horizontal constraint information for the system to come up with just one solution for your view heirarchy. In this instance, it can't determine what the view size or left margin needs to be based on the current constraint information.
You need to add a less-than-required-priority (<1000) constraint either to your view's width giving it a defined width or add an equality constraint to your left margin constraint. By making the new constraint a <1000 priority, it will enable the new constraint to properly mix with your existing inequality constraints (which are required constraints). Here is another question that is similar to yours relating to inequalities.
The view will size differently depending on if you add the new constraint to the view's width or the view's left margin. This all depends on how you want your layout to behave in response to changes.
This does not make sense to the compiler (and logically) because there is no way to know whether the program should change x or width. Making one of the two static will solve your problem.
First you have to know what you want to do with constraints, please remove greater-than-equal-to constraint that does not make scene with less-than-equal-to constraint. buz view need define width constraint. either apply priority to which constraint play role first (greater-than-equal-to constraint or less-than-equal-to constraint).

Resources