I'm wondering if xCode auto layout / constraints are really as frustrating as I think, or am I just not understanding them. For example, I started with this basic label in the view controller:
Fair enough. A box with text that has equal margins on the left/right and a smaller top margin. Now when I run any size device, that gets skewed/cut off from the device view. So right away for some reason Xcode thinks that despite me putting the entire label in the view controller, it things it should display halfway off the screen. Don't get it but okay, so I went ahead and added auto layout constraits to the right, left and top margins. The result is:
So it centered it, which is nice, but now it just ignores the fact that I made the width larger and it just shrinks it down anyways? For something so simple this seems to be very...unreliable. I then added the "aspect ratio" constraint and it seemed to look fine in all of the devices...finally!
I curiously also simply tried to get rid of all those, and simply add the "aspect ratio" constraint and the "horizontal center in container" constraint. On the main storyboard preview (not the simulator) it looked like this:
Not what I'm looking for, as it's not stretched downward like I want, they shrunk it again. However...when actually running it in the simulator...it looks perfect, the way I want it to in the first picture of the view controller.
Why the preview and simulator differed, I suppose (from reading other questions) it's because there were a few warnings after I added these. One was that the horizontal and vertical positions are one initially and will be different at run time. But when I ran it, it definitely held the initial ones and not the ones they said it would be at run time. It also told me that vertical position was ambiguous...well yeah I only set a center and aspect ratio...pretty obvious and not sure how I'd even solve that error. It solves it when I delete the horizontal center...but now it's not centered which is a step back from what I wanted.
Long story short, how do I deal with this. My previews and simulations aren't accurate with each other even for the simplest auto layout specifics. Apps nowadays are so complicated and on every device they scale and work beautifully, and this seems to not agree with even just one label.
Does anybody have any good articles, advice, or anything that would help me? This auto layout stuff seems to be so picky and that's really all I know so I have to deal with it. And don't even get me started on why the text doesn't scale with the label...why would I want the text on an iphone 4 to be the same on an ipad even when my label is increasing in size with the device?
A lot to go through, but it's just very frustrating and I can't see myself doing much else before I try to understand these basics. Thank you and much appreciated.
I think you have to understand constraints first...without that you always made things frustrating....For understand the constraints you can check this links
http://www.raywenderlich.com/50317/beginning-auto-layout-tutorial-in-ios-7-part-1
http://mathewsanders.com/designing-adaptive-layouts-for-iphone-6-plus/
It takes a bit of experience to get used to it, but once you get it, you get it for good and it's very easy.
Basically the rule of thumb is don't trust exactly what you see in storyboard when it comes to the size of the actual object. Say you have a UIView centered horizontally and vertically in the main view. True it will try to keep the size of that UIView but center it in any size device, but I would never just leave it at that. I would either:
Add width and height constraints
Add a width/height constraint and an aspect ratio constraint
Add a width constraint and top and bottom constraints
Add a height constraint and leading and trailing constraints
Add top, bottom, leading, and trailing constraints
In other words, the exact size of the object should always be determined via the constraints, and not by the UIView itself. This gets away from the finicky behavior and also ensures that it's displayed on any device exactly the way you intend it to.
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 have previously worked in Windows phone and see that every control in windows phone has an Auto property, meaning occupy the size of the content.
I see that in iOS such a property does not exist. When there are dynamic data to be bound to a UILabel, I always need to calculate the height of the data and then assign to the UILabel. This takes a good amount of time and bit painful. Is not there an Auto property or am I missing anything here?
iOS has AutoLayout which is really helpful, get familiar with it.
Click on the Label
Click on the pin constraints button (little square button)
Add your custom LEFT, RIGHT, TOP margins or LEFT, RIGHT, BOTTOM margins
Click on "Add 3 Constraints"
Set number of Lines to 0 which means as much lines as view needs
Then you probably got warning lines, but you can solve them
Just click on fix constraints button (little triangle button)
Click update frames
UPDATE
Important: the answer to your question is to PUT NUMBER OF LINES TO 0 you can use that UILabel with 0 lines(which is autosizing) with frames and AutoLayout. AutoLayout is just a friendly suggestion that can be helful to setup views. Also put Line Breaking Word Wrap
Here you go also with some useful links for working with AutoLayout. AutoLayout is great because you don't care anymore what size is the screen, what orientation has the device at that moment. You just need to setup everything correctly and everything works amazingly but if your setup is wrong then AutoLayout might become your enemy. So start learning and experiencing right now.
Very good point to Begin learning AutoLayout
If Your are being lazy, start from video tutorial series
Great iOS7+ table view tutorial with autoresizing cells
Also check out this Stack Overflow discussion
You need to familiarize yourself with Auto Layout:
Auto Layout dynamically calculates the size and position of all the
views in your view hierarchy, based on constraints placed on those
views.
Just give top, left and right constraints and make label's numberOfLines to 0. That's it. Label's height will resize automatically.
In the new "Xcode 6" the ability to change the center of measure of a button is missing.
In Xcode 5: http://imgur.com/jWHJp4v
Xcode 6: http://imgur.com/rsNayVZ
When I put an item (like a button or label) somewhere, I am unsure of the center, so my code that deals with the item is incorrect.
The "center" shown here in Xcode 6 is measured from the top left of the item, not the actual center.
How should I fix this so it is measured from the center like here, in Xcode 5?
You can't “fix it”. That control is gone in Xcode 6. I suspect they removed it to encourage you to use constraints instead of setting frames directly. You can use constraints to pin the center, right, or bottom of a view.
It's driving me crazy that the origin widget has been removed. It has made the placement of any object relative to another very difficult. I always use auto layout and I'm not sure how this improves it. Also, I'm not sure I follow the logic of improving a feature by making it more difficult to use. In the past, it was very helpful to set the "anchor point" of the origin and then adjust the object's position or size and have the frame grow on the unanchored sides. Now i have to break out the calculate and add position + size and then add buffer space to figure out where next object should start. And if I adjust the first object's frame in any way I need to break out the calculator again. Once you have a few objects that are relative to each other, it becomes vary painful to tweak any object's frame without having to recalculating everything.
As a side note, the removal of the ability to delete a constraint right in the size inspect is also a confusing choice. Instead we have to go through the document outline and manually delete them there. This is not a big deal for the size constraints as they are keep in the object's sub-directory however finding edge related constrains is much more difficult as they are grouped with the rest of the edge constrains and can be difficult to find. Again, is this an example of encouraging / improving auto layout? Very frustrating!
The feature has been removed from Xcode. I believe this is to account for the various sizes of devices now available, and as a result, the use of constraints is the way to go.
If you are using auto layout then this two will help you place you control in center for all the view different size of devices.
simple:
http://technet.weblineindia.com/mobile/using-auto-layout-in-xcode-6-for-universal-ios-app-development/
Advance:
http://www.youtube.com/watch?v=G53PuA_TlXk&feature=youtu.be&list=UUtc1Jt_UTPsXpAGtvlr0nUQ
Apple has removed this feature as there are 4 different size of devices only for iphone and it would be difficult to set frame for all controller and will increase the length of code and will become a tedious task as it check's the size of device and then set frame so in XCode 6.0.1 we need to use auto layout + size class and prepare our view based on the constraints set in storyboard or Xib.
Hope the above link's will help in solving your problem.
If your layout isn't too complex you can "Pin" your button or view to the top or bottom, sides, etc.
Or you can do your constraints manually here:
The first method works really well and is super easy! I had a similar problem as you looking for tools that have been left out in Xcode 6 and found this wonderful tutorial on Auto Layout:
http://www.raywenderlich.com/50317/beginning-auto-layout-tutorial-in-ios-7-part-1
If you are trying to center it I would click on the button or view you are working on and look at the size inspector here:
Look at where I circled and make sure that the bottom space and the top space are equal to the same amount (mine aren't equal), but that should give you the center.
I am trying to get this view working with auto layout to accommodate both 3.5" screens and 4" screens. I am starting to feel like it is not possible only using auto-layout and IB.
Any insights? I have tried just about every combination of constraints I think would make sense (and many stabs in the dark) without luck.
Here is how it looks on a 3.5" screen (from IB but looks identical in the simulator)
Here is how it lays out on a 4" screen
Here are the constraints, let me know if there is a better way to show this information.
The simplest (but not best) way would be to take each item on page and add the following constraints
"pin" width
"pin" height
Leading Space to superview
Top Space to superview
Remove all the other constraints.
This should lay out every staticly with all absolute values. It should work fine.... unless you rotate, but I'm not sure if you support landscape. If you do, replace step 4 with "Horizontal Center in Container" constraint.
Side note. Pink constraints are put in by Xcode because it is missing something it needs to position properly (you can't remove these). Blue ones are one you put in. Many times pink ones will vanish as you put in blue ones because you've giving it missing data Xcode needed to position the item.