UITableViewCell sizing with optional image (Swift) - ios

I am having a doozy of a time trying to figure this one out:
I have a UITableViewCell with a fixed sized UIImage (250 x 250) pinned to the top of the cell's View and a UILabel of variable text size underneath with its top pinned to the bottom of the UIImage and its bottom to the bottom of the cell's View.
I have a use case where an image is not always guaranteed and so the image view purposely collapses to 0 height so it does not break autolayout on the UILabel's top pinning.
I assumed that this would allow the UITableViewCell to shrink down to the size of the label but instead, it stays the default height and autolayout stretches the label's height (to maintain the pinning to the top and the bottom) with the text centered in the middle.
I used all the usual suspects, UITAbleViewAutomaticDimension and estimatedRowHeight blah blah (what you would probably suggest first!) and it was to no avail.
What am I doing wrong?
I did see something about changing the Priority for the constraints in IB to 250 instead of 1000 so they could break. And also some references to resizing the UITableViewCell manually (lame and nasty) by calling requiredHeight() on the UILabel which broke the layout, so what am I doing wrong here? Thanks!

I have a use case where an image is not always guaranteed
For this situation you can create 2 type of UITableViewCell: the first one with UIImageView and the second without it. Then, in cellForRowAtIndexPath init the cell you want.

Related

UITableViewCell prevents UILabel from expanding height

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.

How do I change cell height according to its content?

I have a Detail View Controller, which has different text lengths according to which cell you press in the Main View Controller, of which it segues to. How do I set the cell's height according to how much content is in it?
FYI, the cell consists of 3 labels and 1 image view. It is vertically set as UILabel, UIImageView, UILabel, UILabel.
I am using Swift.
This is what happens when I add the auto-layout constraints:
The way to do it is to use auto-layout. You need to set up vertical constraints from the top to the bottom of your cell:
Distance between the top edge of the cell and the top edge of the first label.
Distance from the bottom edge of the first label to the top edge of the image view.
Distance from the bottom edge of the image view to the top edge of the second label.
and so on ...
Auto-layout will take care of sizing the cell depending on the size of the content you put in your labels and the image view.
You should also remember to set the estimatedRowHeight property on your table view to some meaningful value. This will help the table view defer some of the calculations of the content size to when the user starts to scroll.
Also, set the rowHeight property on your table view to UITableViewAutomaticDimension.
There are 4 things you'll need to do:
Set your tableView:heightForRowAtIndexPath method to return UITableViewAutomaticDimension.
Set your tableView:estimatedHeightForRowAtIndexPath to return the average height of the cells. You can set it to something static like 100.
Set your Auto Layout constraints so that all subviews are tied to each other vertically, and the top-most and bottom-most views are tied up to the cell's contentView.
Set the label's preferredMaxLayoutWidth property either in code or in your Storyboard to be equal to the label's width.
To fix this, I added the sizeToFit() property to my label.

Why is contentView height of UITableViewCell always one point smaller than the UITableViewCell?

My cells, at the UITableViewCell level, have a height of 44 points. The contentView says 43 points, and it's greyed out in IB. How can I make the content the same size as the cell?
Note that I'm designing my cells in separate xib files.
I want my cells to have no margin between each other.
I have also set None as separator style of the table view.
Row height in IB is also set to 44 points. Not using any sections.
If you're using storyboards setting the Separator of the tableView to None (instead of Default) gets rid of the 1pt separator and the contentView's height becomes equal to the cell's height (even though it's grayed out)
Note: This solution doesn't work with xib files (at least doesn't update the IB, didn't check at run-time).
I figured it out. I was using full sized background images as background for the cells. As soon as I stopped putting separate UIImageView:s as background in the contentView, and instead assigned the background UIImageView:s to the cell's backgroundView property, and then set the height of the cell as well as the height of each cell in the uitableview (and also set the contentView background color to fully transparent!), things started working as I wanted them to. The contentView height will still be one point smaller, but now the cells align perfectly to each other. For this I don't need to have the contentView height match the UITableViewCell height.

UITableViewCell dynamic constraints

I am making filling a UITableView with custom cells of dynamic heights. I am using the methodology as described here.
For the purposes of simplicity, say my cell contains 2 UILabels as shown below.
The purple UILabel will remain the same height for all cells in the UITableView. In this case, the purple UILabel is taller than the green UILabel. I would like the constraint between the bottom of the purple UILabel and the bottom of the contentView to be 8.
However, there is a second scenario that is possible as shown below.
In this case, the purple UILabel is still the same size as the first case (even though it looks smaller, but since the overall cell height is larger, relatively, it looks smaller), however the green UILabel is much larger. In this case, I would like the constraint between the bottom of the green UILabel and the bottom of the contentView to be 8.
Now my dilemma is that I can set either one or the other (I am using storyboard). But I cannot think of a way to make both possible at the same time. My guess is that you would need to adjust constraints programmatically during runtime depending on the size of the green UILabel.
Any thoughts?
I am using XCode 6.1.1 in Swift.
Thank you.
If the purple label is always the same height, then you should just set the height constraint of the element, rather than setting its bottom constraint to superview as 8.
For the green element, perhaps you could select both that element and the contentview and set them as having equal heights from the "add new constraint" pane at the bottom of the storyboard window. Then, select that constraint and edit its multiplier value in the attributes inspector to some value less than 1. That would make the element's height always be some percentage of the parent view's height. You could tweak that around until it gets you close to the desired 8px from the view below it.

Resize UITextView inside a UITableViewCell with iOS Autolayout

My Goal
I'm creating a custom UITableViewCell (MessageCell), and I'd wish to have my UITextView resizing both in width and height whenever the cell changes its size, while keeping some basic constraint like margins to the edges.
Note : I also change my cell's height in the heightForRowAtIndexPath method depending on the content which will be placed into UITextView.
What I tried
Here are all the constraints currently applied & the cell :
I tried :
With a UILabel.
To fix a Vertical Space from the bottom, thinking it would change the height to fit all the constraints.
To override Height with an User Constraint Height >= 43 (my initial height), but the purple-automatic Height is re-created again whenever I do this.
To find a solution on SO first, but didn't find a case like (even if the UITextView's height's resize with autolayout seems to be a frequent issue).
Plenty of combinations of various & random constraints until my fingers bleds.
How it render now
So...
If someone has any clue or guideline to achieve my goal, I'd appreciate!
I might add, I'm totally new to Autolayout & constraints. My reference : Ray Wenderlich's awesomeness
You need to get rid of that height constraint that the text view has. Make sure you have constraints to something above and below the text view (usually the top and bottom of the cell), and then you should be able to delete that height constraint.

Resources