As seen in the link below theres some margin/padding on the top, bottom, left and right part of a cell. How do I set it to zero? I tried returning CGRectMake(0,0,0,0) in the -(CGRect)layoutMargins margin of the UITableViewCell's lifecycle.
https://www.dropbox.com/s/rl95v2688k70u0j/Screenshot%202014-10-13%2003.29.08.png?dl=0
If you are using AutoLayout (which seems to be the case according to your screenshot) you can reach this be modifying the constraints (the blue lines which you see in Interface Builder). AutoLayout can be tough to deal with at the beginning, but if follows quite logical structures. If you want to get down on the nitty gritty of it and understand how it works I can recommend you this excellent video tutorial from Scotty on the topic.
Another simple way would be to turn off AutoLayout and just set the label to the same size of your cell, so your approach with CGRectMake isn't all that wrong, except that you need to keep in mind that it takes as parameters: x and y coordinates (which you want to set to 0 as you already did) but also width and height (which you also set to 0, but probably want to set equal to the cell's size).
AutoLayout can be turned off in Interface Builder by removing the checkmark in the following picture:
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'm figuring out (again) how to set the margin for a custom UIView instance. From what I recall I had to set the AlignmentRect via the alignmentRectInsets method. But that did not worked with auto layout.
Searching on google I found that there is another property called layoutMargins.
So the question is what does layoutMargins and alignmentRect do ? Do they affect each other? Totally different things ?
layoutMargins determines how things inside of the view are positioned with auto layout. Usually this is used to keep objects a specific distance away from the edges of the view.
alignmentRectInsets is for telling objects outside of your custom view how they should align with it. For example, you might have a view with a wavy or angled top. Aligning other objects with the top of the view may not look quite right, so you might set an inset on the top alignment to compensate.
You probably care about the layoutMargins. I've never actually seen anyone use alignmentRectInsets.
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.
I’ve taken a lot of time to read other questions before asking this one, and haven’t managed to solve the issue yet – hopefully someone can help.
I have a custom alert view, a UIView subclass. I’m trying to get it into a state where its width is fixed, and its height grows dynamically based on the height of its two labels (title and message), and a dynamic number of action buttons it can be set up with.
I’ve used AutoLayout to set up the controls, which is working fine, but for now I’m still manually setting the frame of the view itself in its initialiser.
What I need to do is have the view’s height be calculated by the height of my two labels, and n buttons, plus the spacing between them.
I’ve tried providing an intrinsicContentSize for my view, but that method is never called, and it doesn’t even ask for it, so I’m stumped as to how to proceed.
To summarise: I probably need iOS9’s UIStackView, but I don’t have that luxury, so I need to bake something similar into iOS 7 / 8. I’ve looked at OAStackView but I’d rather not use an external dependency.
Just a quick thought: Have you tried to create the view in Interface Builder? Give it a fixed width with Priority: 1000. Add no Height constraint but center the view vertically in its superview.
Then set the View's vertical content hugging priority and vertical content compression resistance priority to 1000.
This should cause the view to calculate its own height based on its subviews. You only need to make sure, that the subviews are bound to the superview in a way that defines the height without any ambiguity.
i want something who seems simple at first glance, but i can't figure out how to make it nicely from IB.
I want something simple, let's say i have two view into one parent (a view container that hold the two children). What i want is that they are each connected to vertical space at 0 px (one to his top the other to the bottom of the other). So that when one of them change his size the other occupy the remainder size, and so there're will still be connected at 0 pixel each other.
I've put two screenshoots of what i want.
I've tried lot and lot, and nothing is working like i'm expecting.
What is strange that even if i put the priority at the vertical space, the other constraints take priority, and i just get a warning from XCode that my verticalSpace constraint is wrong.
Could someone help me ? I didn't find a specific tutorial on this kind of view managements.
Thanks
* EDIT *
Ok i figured out:
I finally read the entire tutorial of Ray as suggested, and it helped me a lot (to my defense, i have read before the IOS official documentation about constraints, and it has confuse me more than helped me). To me, what was hard to understand is that now you can't change UIView by frame but now by constraint. When I understood this, it was really easy to make the changes.
By the way i tried the #Handsomeguy's response, and it worked like a charm.
I think you'll need at least one height constraint (with IBOutlet to your view controller) on one of your views... when you change its constant value, the other view should automatically change. You can try on storyboard first, and then write down the logic. But without an height constraint on one of them I don't think it will ever work.
I was able to do it by setting constraints in interface builder:
vertical spacing: top layout guide -> yellow
vertical spacing: yellow -> red
vertical spacing: red -> bottom layout guide
height: yellow
Set an outlet to the height constraint, then to change the height of the yellow view just use _height.constant = NEW_HEIGHT
You can probably omit the height constraint if the top view reports it's intrinsic content height appropriately.
Use autolayout. You need the following constraints:
both views pinned to left and right edge of containerView
redView top pinned to containerView top
yellowView top pinned to redView bottom
yellowView bottom pinned to containerView bottom
height constraint on **either* redView **or** yellowView!
This is very easy using this category:
https://github.com/jrturton/UIView-Autolayout
UPDATE
I just noticed you said you wanted to do it in IB. You can use the same principle here, but I find it is much more convenient (and also easier to read later) if you use the category mentioned. There will be very few lines of code, and the code will clearly show the intent.
** UPDATE 2**
An explicit height constraint may not be necessary if the intrinsic size on one view is changed. This depends on what kind of views the yellow and green views are.
Without auto layout it would be as easy as putting an anchor-bottom on the yellow view, and putting an anchor-top on the red one. Now, when you change the parent view, the views would resize 50/50.