In order to get an iPhone layout to display at 'correct' dimensions on iPad, I'm putting everything (rose) into a view (blue) within the ViewController (gold)
Click / tap to see Schematic View
The iPad is shown as the larger frame with the grey status bar.
So to cater for 7plus size iPhones downwards, I'd have to set up constraints for the 7+ within an iPad frame with different priorities
in different directions. Once the blue view is set, i should happily be able to add my Sub Views in I.B.
Since the whole lot has to appear in the very centre of Ipads, step (1) is to set alignment centre-line constraints of the blue View with priority of 1000.
Next would be to fix the size for iPad displays larger then 7+. Acheived with setting size constraints as a maximum to shrink from. I've only shown the ≤680, so that height or less as in step (2) but a lesser priority, say 750.
Then for it to reduce down in size toward SE size i want to hold that say 20 points away from the viewController (gold). So the constraint for that should be ≥20. as shown at (3), I've assigned 740
The principal works nicely in the horizontal direction, but not the vertical. I've tried endlessly to adjust different priority assignments, including the 'Content Hugging' and 'Content Compression Resistance'properties and I never seem to get the desired results once I put the actual entities I want to see (rose) within the Blue view.
I've read Apple's Autolayout Design Guides closely enough to almost say I've written them, and after 35+years of CAD and 3D animation modelling, I think I could describe objects in text parameters before the iPhone existed.
But I've been bested here. Am I taking the long way 'round to just get an ** iPhone only ** layout to display correctly? My little bald spot thanks you for your answer.
If it were me, I'd use trait variations instead of trying to handle layout for every size class in one set of constraints. I think if you take that approach, you can accomplish what you're after with a lot less work and in a way that's independent of devices that may appear in the future.
Also, keep in mind that if your app supports iPad multitasking, you may have sizes on an iPad that you're not expecting (like iPhone portrait width in device landscape orientation).
With autolayout, try not to think in terms of device type or orientation. Think in terms of the appearance you want for a particular size class, wherever it appears, in whatever device orientation. That gives you the opportunity to create a the best user experience for a given display area, and will make your life easier during initial development as well as when new features are added or new user devices are in the mix.
Related
I have an interesting issue with a margin inconsistency between different devices. Here are 2 screenshots from iPhone X and iPhone 6+ respectively with the same iOS (11.4.1) and running the same app.
You can see that on the iPhone X everything is aligned properly (as well as in IB), but on the iPhone 6+ there's a 4 pixel inconsistency.
This is a table view with static cells. All the menu items are the Basic style, except the second one ("Offline mode") which is in Custom style with custom constraints. In basic style the UILabels have X=16. My custom constraint also has a constant value of 16.
Of course, I can change my custom constraint to 20, but then the situation flips. So on the iPhone 6+ it will be all aligned properly, but will be misaligned on the iPhone X.
I tried to find out where these 4 pixels are coming from, but found nothing. Please help.
The problem is that you have pinned your label's leading edge to the edge of the content view with a constant of 16. That is not how the other cells work, so you get different results.
Instead, pin your label's leading edge to the left margin of the content view, with a constant of 0. The left margin is 16 on a smaller device and 20 on a larger device, which is exactly the difference you're seeing for the other cells (because that is exactly how they are configured).
Matt's answer is correct. I just want to add more details, because it may be beneficial for someone else. So, it turns out that all I need to do is to check the following checkbox in my constraint properties in IB:
Looks pretty simple when you know where to look for.
Generally as soon as you start needing to control the margins etc of table view cells your best bet is to leave the built-in stuff behind and make custom UITableViewCell subclasses with explicit constraints and subviews.
In this particular case the screen width is different and the basic cell type calculates its margin constraints relative to the screen width. If you look on the right side you will see the same kind of inconsistency with the positioning of your switch control relative to the disclosure indicator in other cells.
(EDIT: Easiest solution, depending on what you're aiming for, is as matt suggests, pin to the margin of the content view rather and the actual edge.)
If you want, you could adjust your own constraint on your custom cell so that it is not constant but relative. You could figure out what multiplier you would need by looking at a few different device screen sizes to see if it's constant (e.g. iPhone 6, SE etc). But it may be more practical in the long run to use your own subclasses. Note you generally do want to use relative constraints for things like this, since your constant margins might look fine on one screen size but weird on another.
This is not ideal but technically you could also check what device the user is using (or what the view's width is) and return an appropriate constraint using a switch. Although, if you really are only concerned about the iPhone X vs the 6+, then you might want to consider doing that.
You might also want to consider using a form library like Eureka but there's a bit of a learning curve with anything like that, especially when it comes to customizing the appearance of cells and their subviews.
I would like to change view size depending on the screen size of the device.
For example, the view should not have the same size on iphone 4s and iphone 6.
The best way would be to use size class, but iphone 4s and iphone 6 are in the same.
Is there a way to add custom size class in order to do that ?
Or should I set auto-layout constraint programmaticaly depending on screen size ?
Thanks
At this point in time you really only have one solution, and it is using constraints.
Constraints have been existing for a long time now and should be used in all iOS projects. Never EVER change view sizes using their frames. Always adjust the constraint instead.
You can achieve pretty much anything using constraints. There are many tutorials / stack posts about it, you'll be able to look it up.
From what I understand here, you want your view to be bigger on bigger screens, and smaller on smaller screens. Without any other information i can only show you a very trivial example.
Add 4 constraints in storyboard (or in code, but it's just easier in storyboard I believe) from your resizing view to another view. Those four constraints should be Top, Bottom, Leading and Trailing (Up, Down, Left and Right).
Each constraint will basically say "my view should be X units from its superview, on that side".
If you go in the constraints attributes you can configure different things, like "I want my left side to be X units from the right side of that other view".
I suggest you mess around with colored empty views and see how they work, and if you can, have a more experienced programmer answer your questions on the side, because constraints, as simple as they are, are quite confusing at first. It took me about 2 months to be what i consider comfortable with it, and I'm a full time developer.
I can answer a couple more questions here if you want, but I'm pretty sure we'll be off topic really fast !
Have fun using constraints, they're great !
I need to create an app with adaptive UI. for that I use auto layout and size class. but i can't get the expected result. it displays different UIs for different screen sizes. kindly guide me to create the adaptive UI(for all screen sizes). Thanks in advance.
This is indeed problem with constraints as mentioned in comments to your question. Using size classes only allows you to set constraints for all iphones at lowest level (that's why screen size for size class Compact x Regular is same for all iphones in xcode).
It is difficult to help you, without knowing all of your constraints. My advice is, use Preview assistant, where you can see all of your devices and generated UI. By opening this Preview assistant, tap on bottom "+" symbol and add device you wish to inspect.
As you can see on this screenshot, in my storyboard, there are margins around the middle view, however on iPhone 4, where width is smaller, these margins are lower (they have lower priority as constraint), while view retains it's width/height.
I'm a bit stuck and any help would be greatly appreciated!
I'll give you a quick overview. I have designs for a screen that were built in sketch using an iphone 6 screen size, then redesigned to fit and look right for an iphone 5/5s/5c, and 6 plus as those are the only devices that I want to support.
But the design portion or implementing the designs for just one specific screen size is easy and I understand that part. Where am I'm lost completely, is how to implement a design in one view controller that looks the way that it should in all the screen sizes I designed for.
I've gone through more than a few auto layout and size class tutorials and not sure how I properly use them so that the app recognizes "this is an iphone 5, use these image sizing and placements instead, and this is an iphone 6 plus, use these" and so on.
Everything I've seen to this point regarding auto layout and constraints only use 1 set of numbers to judge distance from elements for example, but all screen sizes would have different distances.
What am I missing or not understanding? I know I'm looking at something improperly.
Thanks in advance for all help!
You're correct that just one set of numbers could be used to judge distances, but this can still describe how a view should appear on different screen sizes. Your problem may be that you're thinking of constraints as describing the frame of your view? (Which obviously has to be different on every device). I find it more helpful to think of constraints as describing how each edge of my view relates to another view.
For example here's a view controller I setup with all the same constraints and how it would look on different devices. The constraints describe how the large grey view is pinned it's left and right edges 20 points from the left and right edges of its container view. It's pinned to 8 points from the top and 8 points from the top of the label. The label is centred vertically and horizontally and it has intrinsic content size. Each button is pinned 20 points from the bottom edge with button 1 and 2 being pinned to the 20 point from the left and right edges respectively.
I don't know if that helped or if that wasn't the answer you were after and you need to arrange your views differently depending on the device: you can tell Xcode which device size and orientation the constraints you're creating are for, using this button in Interface Builder.
Use it to select a device size/orientation. After, any constraints you create will only be used on that device. By default any width and height are selected so normally your constraints are applied to all devices.
Also, you cannot choose which devices you want to support, only the iOS version.
I've been having such a hard time trying to figure out how this thing works. It's so random and I have no idea what else to try. I've looked up multiple articles on this issue and everyone just says change the scale. Changed the scale does not help, it's got nothing to do with what's happening here. I'm not sure if this is related to the bottom of Xcode where you can change the dimensions (Any vs Any / Any vs Regular Height, etc...) I've asked my mobile development teacher at school as well and he couldn't figure it out either. Any help would be greatly appreciated!!
Picture below:
http://tinypic.com/r/281fw5w/8
Your problem is not scaling. What you need to look at is auto layout and constraints.
You can use the icons in the lower right edge of the interface builder to get at them or control drag from a view controller (like a button, label, etc.) to the containing view (or any other view controller for that matter.) Usually, the main view window itself. When you release you can now add constraints to "attach" the element to that other element relatively. For instance, you could attach the things on the left to the left side and the things on the right to the right side. Now, regardless of the dimension of the actual device screen, those elements will appear in those locations relative to the device screen.
The problem is that the position of elements from your perspective is right for the canvas you see in the Interface builder, but once the app is run, the real canvas has different dimensions.
To manage the position, size and other attributes of UI elements, there is a system called AutoLayout.
It is quite ingenious because it is similar to natural language.
For example "I want this element to be in the middle of the screen."
or
"I want this element to be 20 pixels from the left corner and 57 pixels from the element that is above this element."
By combining these rules you basically create a set of layout constraints, that are applied in runtime to the view hierarchy and view are laid out properly.
Autolayout allows for very sophisticated layouts.
Another aspect you need to take into account that you might want your app to look well in all form factors from 3.5 inch iPhone up to iPad air.
Since these devices differ considerably in size, Apple introduced an abstraction called Size Class.
Size Class is an abstraction on top of concrete size. Concrete iOS devices have vey concrete dimensions. But in natural language you often say it's big ,or small ,or normal. And this the level of abstraction size classes use.
For each size class you can have a particular set of auto layout constraints.
So by combining AutoLayout and SizeClasses, Apple solved the problem oh how to have one application but one that can still accommodate specific form factors and can adjust its layout to them.
In Xcode6, all storyboards/xib files have autolayout & sizeclasses enabled by default. Interface builder provides you with a comfortable environment where you can set up your layout by creating constraints for each size class combination.