I am attempting to vary my auto layout constraint by iPhone version. The vary for traits allows you to differ by size classes. However all the iPhones in portrait orientation are all compact width and regular height.
Assuming I have an element that is horizontally centered but I want my distance from the top of my main view to vary based upon device size, how should I accomplish this?
You cannot specify screen-sizes or device versions in auto-layout - only size classes.
If relative positioning/sizing doesn't work for you, and you want to do positioning such as 5 pts on iPhone SE and 15 pts on iPhone 6, you have to do it via code. Your options are:
Don't use auto-layout...
Change constraint values (constants, multipliers, priorities, etc)
If you read through Apple's docs on auto-layout, you can see it is targeted toward adaptive interface design, not alternate interface design.
Method 1 : Programmatically changing Constraint Values
If you want to set different constant top values for iPhone variation, then create a outlet of Top Constraint and change its constant value.
_topConstraint.constant = Conditional code for each device.
Method 2 : Setting Adaptive Constraints
Eg: I have taken a view with fixed height = 100, width = 200 and centred it horizontally.
Now it give a proportionate top space as per the device size, please gear up for some maths.
Suppose, the top space in iPhone5 screen = 36 pt.
Total View Height = view top + view height = 36 + 100 = 136
Total Screen Height = 568 Bottom Ratio = 568/136 = 4.17
So, set a bottom layout constraint and add the multiplier as 4.17.
enter image description here
On iPhone 7 plus and other devices, it changes the top automatically.
Related
I am working with xamarin.forms and using constraints to center and scale a logo in my splash screen. The problem is: The constraint that I define to Iphone 5s, 6, 6s etc.. doesn't work to the Ipad, and when I define it to the Ipad, it doesn't work to Iphones...
Does someone know how to solve that?
Iphones contraint (in right positions etc):
Ipads constraint (it's is wrong here):
If you just want to center the logo in the screen, I am not sure why you would go with different Size classes for iPhone and Tablet.
Instead of W-Compact, H-Regular for iPhone and W-Regular, H-Regular
for iPad, I would suggest you to apply your constraint with W-Any,
H-Any & View As should be : Generic.
If you set W-Compact, H-Regular, the constraint applies to
iPhone(Portrait) device.
If you set W-Regular, H-Regular, the constraint applies to iPad
devices(Both Orientation).
If you set W-Any, H-Any, the constraint will be applied regardless of
the device size and orientation.
To Center the logo, I would recommend 4 constraint to be set for the Logo.
Width = Fix Width
Height = Fix Height
CenterX to Parent = 0
CenterY to Parent = 0
-----or-----
Top Space to Parent = 0
Bottom Space to Parent = 0
Leading Space to Parent = 0
Trailing Space to Parent = 0
Set, UIImageView mode to Aspect Fit.
Hope it helps.
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.
How would I achieve that a view spans over the device width on an iPhone 6 in portrait mode and on landscape having a maximum width of say 400px and be aligned to the right side?
Can this be achieved by using device classes and / or vary for traits? What I really want, is that the view adapts to the width of the device: if it is wider than 400px (because I rotated the device to landscape mode or because the app runs on an iPhone Plus or iPad) it should no longer span the width of the display but rather have a maximum width of 400px and sit on the right side. Maybe this can only be done by code?
Thanks for any input.
What I really want, is that the view adapts to the width of the
device: if it is wider than 400px (because I rotated the device to
landscape mode or because the app runs on an iPhone Plus or iPad) it
should no longer span the width of the display but rather have a
maximum width of 400px and sit on the right side.
This can be achieved by setting the following constraints to control the width and placement of your view.
Pin the view to the trailing edge of its superview with constant 0 and a priority of 1000.
Pin the view to the leading edge of its superview with a constant of 0 and a priority of 750.
Set a width constraint for the view, and make it Less Than or Equal to 400 with a priority of 1000.
When viewed on an iPhone 6 in portrait, all three constraints are easily satisfied.
When viewed on an iPhone 6 in landscape, constraint 2 (which has the lower priority) is broken to satisfy the other 2 constraints. Auto Layout will do its best to satisfy constraint 2 and will make the view as wide as possible without breaking the width constraint which is 400 units.
You will need other constraints for your view to establish its height and vertical position.
I don't understand how having together left and right orizontal constraints together.. I still don't understand the exact mechanism beyond interface builder, its constraints and the effective results on the simulator:
I expected the label "ingredienti" in the center of my view (like my input text above with same type of constraints).. Why does it go outside my "screen" in simulation preview?
A leading or trailing constraint (which is what you've set up) sets a fixed distance between the left edge of the view and whatever you've associated it with.
The default simulated size for view controllers in the new universal storyboards and xib files in Xcode is 600x600. But none of the current devices actually have this size.
So, if your label has, let's just say, 100 width, then in order to "center" it using left & right constraints using the simulated interface builder width of 600, we'd create a left constraint of 250 and a right constraint of 250 (250 + 100 + 250 = 600).
But again, none of the actual devices have this width. So if we run your app on an iPhone 6, it'll have a width that translates to 375 "points". If we run it on an iPhone 4s or iPhone 5/5s, it has a width that translates to 320 points.
So, our 100 point wide label is constraint with a constant distance of 250 points from the left edge of the parent view. 250 + 100 = 350. But the iPhone 5 only has a width of 320 points, so part of label appears off the edge of the screen, and the right constraint is broken because the left and right constraints cannot be simultaneously satisfied (you probably have a bunch of warning messages about this in your log when you run the app).
If we want the label centered, we must create a horizontal center constraint (as mikle94's answer demonstrates).
You have to remove left and right constraints from your label and then add "center-horizontally to superview" constraint.
For my 1) portrait only 2) deployment target iOS7/iOS8 app, I have in my design UIButtons which have variable heights, for iPhone 5, iPhone 6 and iPhone 6+. I am trying to use auto layout for this. (Not using size classes though).
Using auto layout how can I specify variable height for UIButton for these 3 screen sizes. The buttons look fine on iPhones 5* models, but thinner on iphone 6/6+. Now in auto layout I can say height >= or = or <= say 55), but how do I specify 44 for iphone5, 55 for iphone6, 66 for iphone6+?
Is this something that I can achieve using only auto layout or do I need to manupulate (frames) it in code? What is the point of me using auto layout then?
In addition to frames my designs also specify different font sizes. How do I go about this. Any best known methods for this, Stack-O friends .. ??
You are correct to ask "what is the point of auto-layout if I have to manipulate frames directly"? Thankfully, you don't have to.
An easy way of doing it is specifying the height in relation to a view of standard height (think a view that fits the whole screen).
For example, we can set our button's height to equal half the height of the view.
This way, the button is always going to scale with the view, either upwards or downwards (size-wise). Auto-layout will guarantee that the relation between them will always be 1/2.
Now the button will be half the size of its superview, regardless of size.
It sounds like you need to be modifying the height constraints constant value.
In your xib/storyboard, create an outlet to your view/controller for the height constraint.
At runtime, probably in viewDidLoad, you will work out which device you're on, and then just change the constant of the height constraint.
CGFloat height;
// if iPhone 5
// height = 44
// else..........
self.buttonHeightConstraint.constant = height;
This will automatically trigger a flag that tells AutoLayout to recalculate frames and layout the view again.
I managed this by adding a Height-Constraint to the UIButton. Make an Outlet and you can set the Height in your UIViewController subclass with _myConstraint.constant = 55;