I have a label in a tableview cell with several constraints in Interface builder.
The cell is self sizing and thats working fine.
My problem is, that the "trailing space" constraint is not working.
The text is not broken and goes to far to the right - out of the screen.
I dont understand this. If someone could help me out, what be fantastic, because I am now searching for hours and dont find the root cause.
The Label is set to 0 lines by:
cell.commentLabel?.numberOfLines = 0
http://picpaste.com/p1-AmKNGkwx.jpg
http://picpaste.com/p2-7ODUyyoc.jpg
The problem is that you're setting a fixed size (600 x 444 - based on your comments above) on your tableview, which is larger than the logical resolution of the width for most devices and this causes the cells to expand beyond the visible area.
So, you must remove the fixed constraints and add some relative ones (for example match the width of the superview & set the bottom of the tableview to the top of your 'footer' - or whatever makes sense in your case... you can even stick with the hardcoded 444 for its height - the width is the important one here)
Related
I have a custom UITableViewCell which has a thumbnail and bunch of text. The row height is configured to be calculated automatically using
tableView.estimatedRowHeight = 129;
tableView.rowHeight = UITableViewAutomaticDimension
The row height should be calculated as exactly 138 points.
Everything looks great on the iPhone 5. However, on iPhone 6 Plus, the auto row height fails INTERMITTENTLY for random rows with the following log.
(
"<NSLayoutConstraint:0x17009ddd0 V:|-(20)-[scoop.ThumbnailImage:0x124d2a5a0] (Names: '|':UITableViewCellContentView:0x124e23200 )>",
"<NSLayoutConstraint:0x17009de70 UITableViewCellContentView:0x124e23200.bottomMargin == scoop.ThumbnailImage:0x124d2a5a0.bottom + 20>",
"<NSLayoutConstraint:0x17009e780 V:[scoop.ThumbnailImage:0x124d2a5a0(90)]>",
"<NSLayoutConstraint:0x17009ef00 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x124e23200(138.333)]>"
)
The last line of the log seems to say that for some reason the row height was calculated as 138.333 instead of 138. I have been banging my head for a while now but I am unable to figure out why this is happening. Can some one please help?
Update: This is how my table view cell looks like.
UPDATE I couldn't get the code out of the main repo since its a part of a bigger project. But I have managed to reproduce the issue with a very simple sane project. Please find it here on github.
This warning is telling you there's a conflict in your constraints.
Reduce the priority of the height constraint to 999 and it will go away. Tested it in your Github project and worked perfectly.
0.333 on a 3x scale display (which iPhone 6+ is) is probably connected with the cell separator.
Note that your constraints don't set up the size of the cell, they set up the size of the contentView. But the cell has to add 2 pixels (= 0.666 points) to the cell height for the cell separator. Autolayout tries to keep view positions on integer boundaries so adding 0.666points to the cell height can result in adding 0.333 to your content height.
You can avoid the error by setting your table separators to None. Although setting up one of the priorities to 999 (usually the bottom priority) as the other answer has suggested is a good solution in general.
The warning is telling you exactly what the problem is, but you may not realize it. The first three constraints are for a 90 pixel-high image that's 20 pixels below the top of its container, and 20 pixels above its container's bottom margin. That's 130, and that's not compatible with the fourth constraint, which wants a total height of 138. However, because the bottom edge constraint is relative to the container's margin, that adds a certain number of pixels more. Either remove the total height constraint (my recommendation), or change the top and bottom edge amounts.
I'm wrestling trying to get some multiline labels behaving inside tableview cells. I've already moved away from stacks that didn't work reliably at all as described in this question
UILabel inside nested UIStackViews inside UITableViewCell sometimes truncating
I fixed one of my views with the help of the comments on that question but another view just wouldn't work for me, even after moving to an autolayout non-stackview setup. I then ended up moving the cell that i couldn't get to work into the view which was working with similar layout and got to a point where i have two cells in the same view, one that worked and one that didn't. I've exported this into a new test app which I've uploaded here
In this app there is a simple tableview with 2 cells within it. One cell displays the large multiline text properly and expands the cell as required. The other cell stops short and truncates the multiline label as you can see here
The two cells to me seem pretty much identical in their constraints so I'm very confused why one works and the other doesn't. Here's an overview of their constraints
There are a few constraints not installed as i've been experimenting trying to figure out what's causing one of the cells to not work.
If anyone could explain to me what is causing these two cells to not behave the same, or more importantly why one of the labels doesn't fill its table cell that'd be really appreciated as I've spent hours looking and just can't seem to figure it out.
Cheers!
Edit:
To explain what went wrong in the first place...
The Right-side "Tags Label" in Cell2 has an Explicit Preferred Width = 300. I don't know the internals, so can't say exactly what's happening, but I get the impression Auto-Layout will take that Preferred Width value into consideration when calculating the text bounding-box height, and then continue on with constraints, content, intrinsic size, etc.
Simply un-checking that explicit option will fix the issue.
Original Answer:
I found it easier to start a new Cell from scratch, rather than try to modify the constraints you had set up, so... This will hopefully be reproducible.
Prep: Add new “Cell3” class; make basic edits to code to accommodate Cell3. I also find things easier if I make some variables for label values and set background colors of elements for easy visual inspection and testing.
Step 1: Add a new prototype; purple background; TableViewCell3 class and “Cell3” reuse ID; stretch it vertically to make it tall enough to work with (it won't affect run-time height).
Step 2: Add a UIView for the Left Side labels. Leading = 8 to Superview. Width = 200; Height = 100; Center Vertically. The Height and Width values will be changed later.
Step 3: Add the two Left Side labels - 1 and 2 (Body font) - to the UIView. Constrain 1 Left = 0; Top = 0. Constrain 2 Left = 0; Bottom = 0.
Step 4: Add a vertical spacing constraint from 2 to 1 of 7.5 and change the Height constraint of the UIView to >= 20 (runtime will likely always exceed 20).
Step 5: Change the Width constraint of the UIView to >= 40 (runtime will likely always exceed 40); Add Trailing Space to Container constraints for both Left Side labels, and set them to >= 0.
Step 6: Add Top and Bottom “to Superview” constraints to the UIView of >= 0.
Step 7: Add the Right Side label (Caption 1 font, number of lines 0). Constrain Top >= 0, Right = 0, Bottom >= 0, all to Superview; also Center Vertically.
Step 8: Add a Horizontal spacing constraint from Right Side label to UIView, set to 20. Give Right Side label a Width constraint = 40 (runtime will likely always exceed 40), and set the Priority to 250. This allows the UIView containing the Left Side labels to be in control of the widths.
Step 9: Assign IBOutlets and run the app. Try changing up the text. Make the left side labels shorter or longer... try setting the right side label to only enough text for one line... etc.
At this point, things should look pretty good - until... you put too much text in one of the left side labels, at which point you'll have a very, very narrow, very very tall right side label. So...
Step 10: Add another Width constraint to the UIView and set it to <= 200. Depending on your actual content, you may want to modify that - or perhaps set it to <= to a percent of the width of the cell.
I updated my original GitHub repo so you can check it out. It should have a commit for each "step" listed above, which might make it easier to follow along - https://github.com/DonMag/CellTest2
Results:
Either I'm out of my mind, or AutoLayout is straight broken. Can someone please explain this to me. I have a TableViewCell in a TableView that spans the width of the ViewController. I put 4 Labels inside my TableViewCell. I created constraints using AutoLayout such that each label is 25% the width of the TableViewCell. And yet, the 4 labels are CLEARLY different widths and they don't even add up to 100% of the width of the entire cell. Here's the screenshot. (Horizontal position of each of the labels is ambiguous, yes, but that shouldn't make a difference). Why are they not the same width? And why does 25% + 25% + 25% + 25% not add up to 100%? Running XCode 7.2 and targeting iOS 9.
This red error symbol is Interface Builder telling you that it cannot solve your constraints. In this case, as you have said, it's likely because you have not provided x position constraints for the labels.
Auto layout can either solve all constraints and get a right layout, or it can't and the result will be undefined. Remember that auto layout is an algebra-based process that solves for unknown values by using known values that you provide in constraints. If you don't provide sufficient and unambiguous known values, the equations for the remaining values simply cannot be solved and there can be no expectation of a correct result. The solution is to create enough constraints to make the layout solvable.
As a note, as of iOS 9 I would suggest using a UIStackView to hold those labels. UIStackView exists precisely to take the pain out of setting up manual constraints for these types of scenarios. If you used a horizontal stack view in the cell, you would constrain its edges to the cell's edges, drag the 4 labels into it and set it to "Fill Equally". And that's all you would need!
Daniel Hall's answer has useful information, but doesn't tell you specifically why you're seeing what you're seeing, so I will.
Xcode doesn't always enforce your constraints in the storyboard editor until you ask it to. In this case, you can select the table view cell's content view and from the menu bar choose Editor > Resolve Auto Layout Issues > All Views in BBRowTableViewCell > Update Frames. (Sometimes it takes two or three tries for Xcode to get everything right.)
However, you probably won't like the result. Because you haven't constrained the horizontal positions of the labels, Xcode will probably pile them all up at the left edge of the cell, or maybe somewhere outside the bounds of the cell where you can't even see them.
If your deployment target is iOS 9 or later, the easiest solution (as Daniel Hall said) is to put the labels in a UIStackView set to “Fill Equally”, and constrain the stack view's edges to the cell content view's edges.
If your deployment target is earlier than iOS 9, then you should create the constraints described by user3802077.
This is not the only way, but here is how I usually do it.
As you did for the top and bottom for each labels, then:
Leading of label1 to leading of superview
Trailing of label4 to trailing of superview
Then a constraint for each neighbouring label:
label1.trailing to label2.leading,
...
Then put an equal width constraint from each labels to label1:
label2 to label1
label3 to label1
label4 to label1
This should be it. No need of specifying 25%.
For autolayout constraints it requires to give for constraint to particular object
x,y position and hight , width
If you are not giving any one of this it shows error to you.
So make sure to give all the require constraints to your object.
Other option is uistackview for the ios 9 and later.
Here is a link for you to learn about stackview
https://m.youtube.com/watch?v=XqVWyA5PLwk
Is there a way to achieve this? I have tried literally everything and nothing has worked for me yet.
So basically what i want to do is the following: I have a scroll view with some labels in it. All the labels get their text from a server and I have set their number of lines to 0 so that they change their height according to the amount of text. However, this does not affect the scrollview content size(even though my labels have constraints set up to the bottom,top,leading and trailing of the scrollview) and the labels go off screen and I am unable to scroll down. Can someone point me in the right direction to how I would set up my constraints, my view hierarchy and etc?
Any help is much appreciated! :)
Late, but this solved it for me:
Set leading (I have a 32pt inset), trailing and top constraints. The trailing will not actually seemingly do anything..
Make the trailing Greater Than or Equal to avoid localization alert.
Finally, add a new Equal Width constraint to the label matching the scrollview. Use the constant to subtract the required padding (I used 64 due to mirror my leading inset).
And voilà! The Label will align correctly both in IB and in-app.
In Scrollview the last view's bottom constraint is so important. You should set its priority to 250 and put it to Greater than or equal.
Remember you should only change the bottom constraint of the last view, which in my case it's the continue button.
I would consider using UITableView instead, it has several benefits:
It allows for reuse of cells, if all the cells look the same
It manages recycling of cells when the number of values you're getting from the server increases (decreases memory pressure when number of cells becomes substantial)
It allows for more flexibility with the content (it's quite often for design to change last second or to evolve over the course of the project)
Most importantly, UITableView support auto sizing cells (as of iOS8), you need to specify the constraints between the label and the borders of the cell
There are several resources to start with:
http://www.raywenderlich.com/73602/dynamic-table-view-cell-height-auto-layout
https://www.captechconsulting.com/blogs/ios-8-tutorial-series-auto-sizing-table-cells
http://www.appcoda.com/self-sizing-cells/
Use a container view in a scrollView
Add constraints to superview (leading, trailing, top, bottom, height,width)
Make IBOutlet of constraints that you are going to update.
Add you all labels inside that view.
Update constrains/frame of your label so that it fits the text.
How much you increase the label height you should increase the container height too.
If the label count is not fixed use custom label class to add subview.
Perhaps you should need to understand how ScrollView works in Storyboard with autolayout.
Having a strange issue using Auto Layout with a UILabel where it resizes almost to its content size less one line (driving me nuts). So basically, it seems to get to where it should minus a few pixels causing an ellipses at the end when downsizing to the iPhone 5 or 6. It works fine on the 6+, which is what the XIB is sized for.
Here's what the XIB looks like and what I have the constraints set to. The label is the "Big long label here is the event description".
Based upon this stack post, I thought I was going to figure it out. I tried both methods mentioned in the post. All four of the constraints in the screenshot are set to 1,000. If I do what the post says and add a height constraint with priority of 500, which is less than the vertical hugging and vertical compression resistance priorities, it still doesn't work. I've also just not set the height constraint, kept the preferred width set and had leading and trailing space constraints set, which was mentioned in the comments. The number of lines is set to 0.
To try to give more detail, the UILabel is in a UIView set as contentView. I then add the contentView to a UIScrollView. The UIScrollView is being automatically sized by pinning the contentView at 0 to all four sides. The contentContainer is also constrained to the screen width (not ideal but only way I've been able to get it to work - not sure if it has anything to do with this issue). I'm not getting any constraint issues in the console. translatesAutoresizingMaskIntoContraints is set to NO for the contentView. Here's what the UILabel looks like when ran:
It should be one line longer at the bottom to fit. Someone please help me!
I think I might have solved this, but the solution seems hacky. It seemed to be an issue of setting the preferredMaxLayoutWidth. It worked fine for what I had set for the iPhone 6+, but for some reason almost got there with significantly less width on the iPhone 5/6. Just added this:
self.eventDescriptionLabel.preferredMaxLayoutWidth = self.eventDescriptionLabel.frame.size.width;
And now it works fine.