I'm trying to solve this Auto Layout puzzle with a custom UITableViewCell which contains two labels that may grow vertically depending on their content i.e. number of lines. I've almost got it right, except that one label in one cell does not grow as expected! Please see screenshot where highlighted in red dashed line – the label does not end with a bracket, its text is clipped instead.
Please find the simple Xcode project here.
In my case there are two multiline labels and not just one as in other posts, and so there are 2 elements that effect the height of a cell. But regardlesss of that the soluion is to force the cell to do its layout.
So after calling dequeueReusableCellWithIdentifier() to get the cell, just add:
// fix for iOS lauout bug
cell.setNeedsLayout()
cell.layoutIfNeeded()
All starting and ending brackets are visible i.e. to text clipping :-)
Related
I have a TableViewController with a custom UITableViewCell containing a single UILabel. The label will receive variable lengths of text, and should resize in height accordingly. I want to use auto layout, iOS10++.
However, it seems that the cell is preventing the label from expanding its height.
I have constraints on the label to pin top, bottom, left and right to the cell's contentView.
The label number of lines = 0, and is set to line break mode = WordWrap.
I have set the self.tableview.rowHeight to UITableViewAutomaticDimension, and have set the estimated row height to various sizes with no success.
I have increased (and decreased) the label's content hugging priority and and the vertical compression resistance, but this has no effect.
This sounds like a duplicate of so many other questions, but none I have read has solved my problem.
Some clues I have noticed:
1) If I remove the label's bottom constraint, the label expands correctly, but (of course) the cell doesn't expand, so the label cannot be fully seen after it expands below the bottom of the cell. So I conclude that the cell is preventing the label from expanding.
2) if I rotate the tableview to landscape and back to portrait, the first cell expands correctly. So something that occurs during the rotation solves the problem at least for the first cell, and also proves that the cell and label can expand as required.
I feel something is not right, but cannot figure it out. I am very close to going back to the old version of calculating the height manually and returning it in heightForRowAtIndexPath delegate method.
I would appreciate any suggestions. Thanks in advance.
I finally figured it all out.
In summary, I was configuring the cell (including setting the label's text) in tableView willDisplayCellAtIndexPath...
But it seems (obvious really) that for the autoresizing to work, the cell must be configured in tableView cellForRowAtIndexPath.
Moving the configuration into cellForRowAtIndexPath and suddenly everything started working perfectly.
Hope this helps anybody who has the same problem. I struggled with it for days.
i just created a uitable view with dynamic cells, and as you can see with the insets, the cells have a correct width. But as shown on the image, the label goes out of the screen. I've set truncate tail, fixed font size... I can't manage to get this text truncated.
Should i do it programatically when creating the cell.text.value?
Help is very much appreciated here.
You might not have set frame in LayoutSubviews(). Initially when tableviewcell loads it always gives same width value but when layoutSubviews gets called it gives correct frame.
If you have done it in storyboard then you might have given hardcoded value.
Use Custom TableViewCell's
You can design the way you want and also you can set label/title width height font etc easily .
Make sure you register your tableview cell in viewdidload() or else it will crash
Here are two stack views, each with the same content - the text of the top label is this is a really long label that will extend past the right edge
The top one does not have a Trailing constraint.
The bottom one does have a Trailing constraint of 8.
That really looks like the issue you are running into.
Solved the issue. Initially i had dropped a table view inside the view controller and set the prototype cell to 1 in IBinspector. For an unknown reason, the constraints were not working. Ended up setting protoype cells to 0 and dropping a new table view cell from the object library.
That did the trick.
I have a UITableViewCell that contains two labels positioned vertically one on top of another, and I am using AutoLayout.
The cell works (and looks) fine when both labels have some text.
Sometimes, though, the top label does not contain any text, and in this case I would the cell to have the same height, but the bottom label to be centered vertically. Is it possible to do it with AutoLayout without modifying the constraints at run time?
I don't believe this can be accomplished without modifying something at run time. I see a few options if you'd like to do this without changing constraints programmatically, some messier than others:
First option, you could set three labels in the cell. Two labels that are stacked vertically and one that covers the whole cell vertically, fully overlapping both other labels. At runtime you can determine if the bottom label shouldn't contain text and then set the overlapping top label with the text you would have previously set on the top vertically stacked label.
Second option, you could utilize a label that has the height of both labels you currently have. Set this new (2x height) label to allow for 2 lines (can be done in InterfaceBuilder side options). Then at runtime interpolate the label.text attribute with both label's text. Put a new line character in between the labels if the second label has text. It would look something like this
In Swift:
my2xLabel.text = "\(firstLabelString) \n \(secondLabelString)"
In Obj-C:
my2xLabel.text = [NSString stringWithFormat:#"%# \n %#", firstLabelString, secondLabelString];
All of this being said, modifying the constraints at runtime may be a less hacky way to achieve this formatting.
Make two prototype cells then. One will be the one you have right now, the other would contain only one label but centred vertically. Check if the text would be empty, return the cell with the vertically centred label. Otherwise, return the other cell.
Question: How can I use constraints in a UITableViewCell using UITableViewAutomaticDimension when there are labels side by side which can each contain a different number of lines?
I have a table with cells that contain labels side by side:
I'm having a hard time getting the cell to size properly if one of the labels on one side have more lines than the corresponding label on the other side. One of the labels always gets cut off. If both labels have the same number of lines, the cell resizes perfectly and all text can be seen.
I've tried a number of constraint tweaks but nothing is working perfectly as desired.
I've tried adding hidden label for height...but it doesn't work well for the cell with 4 labels
I've tried placing the labels in a view but then the height of the view still needs to be calculated.
Currently the constraints are setup normally: top, bottom, left , right, labels are set to 0 lines etc and works great when both labels have the same text or same number of lines.
Is there any way I can do this with constraints? Or do I need to revert to the old height for row at index path? =(
There is a way to achieve what you want to do just using constraints. The trick is to set the relation of the constraints between the two lower labels and the bottom to Greater Than or Equal instead of equal.
Here is how I set the constraints:
Which has this result:
Or you could set the constraints between the labels top and bottom to Greater Than or Equal and leave the bottom constraint at equal:
To get this result:
I found a solution where I did not have to revert to using tableView:heightForRowAtIndexPath.
I added a label to the cell with the text color set to clearColor and called it 'heightLabel'. I added constraints to the heightLabel so the cell would resize based on the heightLabel's constraints.
Then whichever of the left or right labels had the most text, I placed that label's text inside the heightLabel.
The cells still were not resizing and I had to call 'layoutIfNeeded' on the cell before returning the cell in tableView:cellForRowAtIndexPath.
The heightLabel constraints are now what is being used to resize the cell and UITableViewAutomaticDimensions is working properly.
This may not be the best solution but it's working out pretty well. If there is a more proper way of doing this I'm open to suggestions.
I've been fiddling around for a bit to try and get this to work but for some reason I can't get the content in this tableView to stay inside the cell.
The following image is a screenshot of my storyboard where I define the tableView. You can see that there is amble space.
But then in the simulator you can see that the content is leaking out of the cell into other cells.
If I scroll then the cells crop the text but do not grow in height.
Not sure what kind of information will help out with this.
I have constraints added to the cells defining height, not width, as well as trailing edges and tops of the cells. Nothing crazy that should be causing this.
I'm defining the row height in the storyboard as such:
Define your row height from your TableView attributes inspector and uncheck the "Custom" option in your UITableViewCell as you show above.