UITableViewCell margin inconsistency (Static cells) - ios

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.

Related

Constraints with static cell are ambiguous

I'm having some problems with properly setting up my static cell the way I want it while making it look good for different screen sizes.
Somehow I don't seem to get how constraints are supposed to work.
One of my views contains a UIViewController with a table view. However, if I change my preview device in the storyboard to, say, an iPad, the table view doesn't get resized. Am I supposed to handle stuff like this from code only or is there a way to handle this from the storyboard (like setting width and height to always fill)?
I'm trying to set up a static cell so it looks good on devices with different screen sizes. Things work well enough when I have only two elements (e.g. one label left and one label right - just like in the standard template), but as soon as I add more things, I'm running into a lot of warnings, e.g. that width and height are ambiguous.
To me, it seems like I'm missing some key concept of constraints.
Look at the picture provided. What I want is the following:
Date to be a certain distance away from my left table border
The Stack View of volume + pic in centered in the middle
pic & price & label (there is one more for the measurement) to be represent the right label
I'm unable to actually try this at the moment but here's the path I would go.
Date:
Fixed Top, Bottom, & Leading to Container constraints to 8 (or whatever you'd like).
Volume Stack
Fixed Top & Bottom to Container constraints to 8.
Price Stack
Fixed Top, Bottom, & Trailing to Container constraints to 8.
You'll have some overlap issues with smaller screens at this point. You should get the "Red Circle" to suggest which constraints to add. Click and read each one and it will be specific enough to walk you through which you want resizing, resetting priority, etc.
*I hate dealing with constraints.
Good luck! I'll try tonight to see if I gave an acceptable answer. :)

Size classes and auto layout for iOS development

I am trying to create a simple UI that works on all devices (obviously) and I haven't had much success. The program consists of two labels, a button, an image view and a textfield, I am also using a universal storyboard.
I implemented a top constraint, horizontally centred and fixed the width and height for all labels, buttons and textfields. The only exception I made with the image view was that instead of implementing a top constraint, I used a bottom one instead as I have found that utilising the former would result in it being only partially displayed. I would then switch from the universal storyboard to one with base values. From their I would delete the existing constraints and add new ones after moving the UI elements to their new locations on the different sized screen.
When I run my app on an iPhone 4S, the layout, whilst mostly correct, is still not perfect (i.e. a label is far too close to the image). Does anyone know how I can make my layouts look correct? I have been following this guide, Adaptive Layout Tutorial in iOS 9.
Thanks so much for your help!
[Example of the constraints for the picture1
I am not sure how familiar are you with autolayout, therfore I'd suggest you watch Stanford university lecture regarding autolayout.
In short, according to the lecture and after looking at your picture, you should almost never set constraints with actual numbers. Use "Standart value" and when you can't choose "Standart value" write 0.
I'd recommend watching the above lecture and the rest of the examples in there.
Your label has 2 problematic constraints
1. Top space (30 points) to "how old is your dog"
2. Top space (28 points) to button
That means that your button is 2 points height (really small!!)
Or - because the button has already a fixed height, the label and the text field are too close (and maybe even overlaps the button)
You should delete the top space constrain (to "How old is your dog") and do something else, or give it more points height
Good luck!

Xcode : changing view size depending on screen size

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 !

Constraints for universal storyboard on iPhones

I'm struggling a bit with constraints on iOS with the differents screens sizes nowadays.
I tried google and stackoverflow to find a solution but my english does not seem fluent enough to find an answer.
I got 4 buttons verticaly aligned, the first and the last one are constrained by the edges of screens (kinda easy). But I'm really struggling with the constrains of the 2 middle buttons. I can't find a way to make them equally spaced from the left and right buttons on every size screens.
Is there something easy and tricky to make these constraints right ? Or am I doing it wrong and should I try to do it programmaticaly ?
Thanks
Add three invisible views in middle of each button, make their width equal with each other with constraint then your four buttons will be equally spaced. For the Y then you just need to pin it at your desired place.
If you are going to support only iOS 9 and higher, then use a UIStackView.
The solutions to this problem is very simple. This can be solved using the concept of "spacer views". You have to place invisible views between each red coloured view. You would be requiring 3 in your case. Then make their background as clear colour. .
Next, make their width equal and constrain their edges to the views that are after and before that view. You then define the size for red coloured view.
REMEMBER dont give the "clear coloured views" any fixed width. It would be determined by the runtime.This would solve the problem. Tell me if any more information is required.
Here is a blog post for the solution for this
http://adamdelong.com/fluid-layouts-with-auto-layout-size-classes-spacer-views-and-constraint-priorities/
This is the youtube video for this
https://www.youtube.com/watch?v=eSG-3-QpmWk&feature=youtu.be
Besides Tj3n's answer with views between buttons, you could use
A UIStackView (iOS 9!) where you use for settings Axis: horizontal, Distribution: equal spacing
A Toolbar (depends on what you want to do with your buttons) with toolbar items and flexible Space between them
Why not size classes? Apple introduced the concept of adaptive user interfaces in iOS 8 relying on a combination of Auto Layout and size classes.
If you aren't aware of what is size classes, there are plenty of tutorials available, please find one.
Summary: Apple very cleverly removed two story borads for iphone and ipad and made a single story board for universal app. No you dont have to struggle trying to apply autolayout constraint that satisfies all the screen sizes :)
Below are few of the size classes and their meaning :)
Regular width x Regular Height ----> iPad Potrait mode/ipad landscape mode
Compact width x Regular Height ----> iPhone 6 plus,iPhone 6,iPhone 5s,iPhone 5,iPhone 4s potrait mode
Compact width X Compact Height ----> iPhone 6,iPhone 5s,iPhone 5,iPhone 4s landscape mode
Regular width x Compact Height ----> iphone 6 plus landscape mode.
You can select the size classes you want to support from story board :) and start applying constraints specific to each size classes (like buttons in middle) or if you have generic one (like your buttons fixed to screen) for all the size classes.
You can deploy, remove, reuse or delete the constraints form various size classes.
SUMMARY: Buddy, If you are not using size class yet, its a high time to start using it :) There is a wonderful video on it in apple WWDC sessions 2014 i believe. Download, watch, start playing with it.
Happy coding :)
you can use equations to get this appearance.
use views' trailing points to get this.
View1.trailing = superview.trailing*(2.0f/9.0f)
View2.trailing = superview.trailing*(4.0f/9.0f)
View3.trailing = superview.trailing*(6.0f/9.0f)
View4.trailing = superview.trailing*(8.0f/9.0f)
if you make View1.width = superview.width*(1/9.0f) you can achieve what you want.
there are a lot of similar solutions for this issue. but the base is using trailing points.
It may also be done with using centerX positions of Views.
View1.centerX = superview.trailing*(3.0f/15.0f)
View2.centerX = superview.trailing*(6.0f/15.0f)
View3.centerX = superview.trailing*(9.0f/15.0f)
View4.centerX = superview.trailing*(12.0f/15.0f)
Thanks to LearneriOS answer, I solved my problem.
In order to get my wished result, I created 3 views with 10 width.
My first and my last button were already constrained. I constrained my first extra view to my first button with Horizontal spacing then i constrained my first extra view with the Center vertically in container. I then constrained my extra view to his own width and heights.
There come the important part: I did go on the constraint menus and selected the width constraint. The value inside was still 10 but I did change the priority from 1000 to 750.
Then I did copy my first extra view and constrained all of them to the nearest buttons, the same way I did with my first entra view but I removed their width constraint (to all the extra views but the first one) and constrained the extra views with the first one by plugging the: Equals Width.
Then I got my result, I hope it was clear enough and thanks again.

iOS / XCode Auto Layout Woes. Easier Way?

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.

Resources