Managing dynamic height for UITableviewCell using iOS 8 - ios

I am trying out autoLayout features for dynamic height for UITableViewCell in iOS 8, I followed this blog http://www.appcoda.com/self-sizing-cells/. So here they mention that from iOS 8 managing dynamic height is hassle free.(In the link they have used swift, but I am using objective C)
Now after doing autolayout from xib, then we need to just write this lines of code in viewDidLoad
- (void)viewDidLoad
{
m_tableView.estimatedRowHeight = 83.0f;
m_tableView.rowHeight = UITableViewAutomaticDimension;
}
This is fine and my tableView height changes dynamically based on the content.
I want to know how to have more control on UITableViewCell height.
1) In my app, I want the cell height to be based on the content(data), but I need to have a default height, which will be applied if the content height is less than default height.
2) I want to know what will be the final height of the cell, before displaying to the user, because I want to add some UI elements below each cell.
So what functions I need to use to fulfil my tasks.

You would need to make sure your Storyboard prototype cell has NSLayoutConstraints from top to bottom. Dynamic cell sizing compresses whatever layout constraints you have in place to their maximum compression given the content set in cellForRowAtIndexPath to calculate the final rendered height of that cell. It is very convenient but it also means you need to be careful about setting your constraints correctly.
If you are adding any subviews programmatically, you need to ensure the same rule of thumb is true- there is a complete, deterministic set of constraints from the top of your cell's contentView to the bottom. Additionally, you will need to set any subviews' added in code translatesAutoResizingMaskIntoConstraints property to NO.

Related

What actually defines the height of a UITableViewCell?

I'm working on an iOS App right now and I want to build a view controller that uses a UITableView to create new events in a calendar (very similarly to how iOS handles event creation in the system calendar, actually). The table view has two sections, the first section holding a date picker and the second section holding two custom cells for entering an event name and notes via a text field and a text view. After playing around with them I managed to force-set them to the right size, but in the process I realized that I don't actually understand how iOS calculates individual cell heights, especially in a table view with multiple sections and multiple custom cell classes. So far, I've found a number of things that seem to play a role:
Contents of a cell, e.g. a text field and its constraints
Hugging priority and compression resistance priority of a cells content
Settings for row height and view height in the size inspector of the cell itself:
Arrangement and Autolayout settings in the size inspector of the cell
Settings for the rowHeight and estimatedRowHeight properties of a UITableViewController
The more I look into it, the more complex and confusing it all gets. Maybe one of you can shed some light on this shady bit of Swift magic?
Basically, the rule is that if the table view's rowHeight is UITableView.automaticDimension, then as long as the estimatedRowHeight isn't 0, you'll get automatic row heights, meaning that the height is determined by the cell's autolayout constraints from the inside out.
The settings can be made in respect to the table view as a whole (in code or in the storyboard) or for a single cell using the height delegate method.
Add your constraints in the cell in right way.
don't use tableview "height for cell" delegate method.
use this in your viewDidLoad
self.tableView.estimatedRowHeight = 44.0
self.tableView.rowHeight = UITableView.automaticDimension
I would say that table view has a bit tricky.
Originally it needed to know size of cell before the cell was created.
The height of cell is defined by UITableViewDelegate optional function tableView(_:heightForRowAt:)
If this function is not defined (or delegate is set to nil) then it will take value of tableView.rowHeight
For performance reasons there was also added tableView(_:estimatedHeightForRowAt:) and tableView.estimatedRowHeight
The idea was not to calculate height of every cell during fast scrolling (such calculation may be costly) and use height that is good enough.
So that are the basics before constraints layout.
Then magic came. You can return UITableView.automaticDimension as height (by delegate method or by setting tableView.rowHeight). It will force tableView to calculate height from cells' constraints (note that constraints must define that height so very likely you want to set content hugging and resistance priority of every label, and you will encounter 'errors' in storyboard/xib).
Since that operation is costly you Apple forces you to specify estimated height by yourself. Also it's important to set that value to something that makes sense, otherwise things like programatically scroll won't work correctly.

How to create UITableViewCell with dynamic cell height based on its content

I was trying to explore the new feature of dynamic cell height using auto layout, introduced in Xcode 7 using this link. I have one UITableViewCell like this below
I want cell to adjust its size automatically based on the content in textView and size of image. I set all constraint and given estimatedRowHeight and UITableViewAutomaticDimension as tableview row height. But when i run the app i'm not able to see the UITextView below. Which means that cell height is not getting adjusted dynamically. Do i need to set the cell height programmatically or still i can do it using Auto Layout.
For TextView, it must not be scrollable.
Also, Your constraints are should be provided in such a way that, TableViewCell should get height automatically(there must be vertical spacing constraints between each component, Height of the each component must be there(it may be explicit of implicit height, but it must need to have height)).
Also, estimatedHeight you are providing must be near to actual average height.
If your tableViewCell is getting above things, then and then only it will get dynamic height based on its content.

UITableViewCell of mixed xibs and programmatically generated UITableViewCells

I have to integrate a UITableViewCell generated programmatically from code like so:
UITableViewCell *newCell = [[UITableViewCell alloc] initWithFrame: CGRectMake(0,0, screenWidth, 150];
However the rest of the cells in this table view are generated with xibs that rely on autolayout, and so the original programmer only used the estimatedHeightForRow method rather than the heightForRow.
My programmatically generated table view cell is all botched (has the default estimated height of 64 rather than the frame's height of 150) unless I implement heightForRow whereas the existing cells are botched as soon as I do implement heightForRow in addition to estimatedHeightForRow. Is there a way around this conundrum?
Thanks for any advice.
Firstly, you should use UITableViewCell's designated initializer - initWithStyle:reuseIdentifier: instead the UIView's initWithFrame:. However, I don't think that is the cause of your problem as I have tested initWithFrame: and it appears to default to default style and no reuse identifier.
You haven't said what you are doing with the cell once you instantiate it. Are you using the default layout or adding your own custom views? The default layout (with just a line of text) appears to work correctly in my testing, with the cells being sized according to the amount of text in the textLabel.
If you are adding custom views you need to ensure that the contentView has vertical constraints that fully define its height. For example, if you have two UILabels vertically aligned then you will need a vertical constraints such as #"V:|-10-[label1][label2]-10-|". If the constraints are not fully defined then contentView will collapse to zero and your views will appear overlapping the next cell.
To give a little more detail, when using self-sizing cells UITableView does not look at the frame of the returned cell but rather calls the cell's systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:. This results in the Auto Layout engine analyzing the cell's constraints to calculate the appropriate layout size. UITableView then sets the cell's frame according to that size and its position in the table.
I would put an if statement in your height for row method and set the heights to their corresponding cell. It would also be easier if I could see code.

UITableView resize cell based on content

Hi I need help with understanding how to resize cell based on its content.
So first of all of course I found many links:
iOS: Multi-line UILabel in Auto Layout
https://www.youtube.com/watch?v=CkvZEJ7dIfw
https://github.com/williamhqs/GSTableViewDynamicHeight
As we said about git example (last link) I can't understand how to change some label and make it works. For example if I delete UILabel and create new one and bind it with content property (content - it is IBOutlet property of bottom label). I seems lost some setting and cell won't stretch.
So I think I don't know to much understanding how to do it.
What I want to understand:
How to setup auto layouts in the storyboard or programmatically.
Which thing I should handle programmatically to make it done.
How the preferred size affects on label. Do we need every time use bonds of superview as a preferred size?
Also in the git example we have one label that changes itself size. What if we have 2 UILabels with dynamic content how to setup it?
If you have some links or videos please drop them here, because I really stuck. Thank you!
I know it's duplicated question but I can't understand how to setup it.
To make Self Sizing Cells works there is three steps:
Setup correctly the constraints of the cell (most important the top and bottom constraints)
Specify the estimatedRowHeight of your table view
Set the rowHeight of your table view to UITableViewAutomaticDimension
for step 2 and 3 it's so easy just add these two lines in you viewDidLoad method
tableView.estimatedRowHeight = 44.0 // or whatever you want
tableView.rowHeight = UITableViewAutomaticDimension
for step 1 which is the most important part of self sizing process
what you need to keep in mind is that "self-sizing needs to get its size from your constraints."
Basically we need to make sure that top space and bottom space constraints of our cell is correctly set up here is an example :
just two labels with the constraints top,bottom,right and left space to each other and to container (see image) the UILabels Lines property is 0 so that you allow have multiple lines
Another example from a project that I am working on:
bottom line:
The label constraints should push against the size of the table view cell and make it taller. So always check the top and bottom constraints.
Also you may run intro trouble working with UILabel with multi-lines because
The intrinsic content size of UILabel and NSTextField is ambiguous for
multi-line text.
so make sure always to setup the preferredMaxLayoutWidth property of yout label:
- (void)layoutSubviews
{
[super layoutSubviews];
self.contentLabel.preferredMaxLayoutWidth = self.contentLabel.frame.size.width;
}
for more infrmation about this issue here read :
iOS Autolayout multi line UILabel
iOS multi-line UILabel in Auto-layout
preferredMaxLayoutWidth
And for more information about Dynamic Table View Cell Height in general here is some useful resources:
UITableView Tutorial: Dynamic Table View Cell Height
Understanding Self Sizing Cells and Dynamic Type in iOS 8
Self Sizing Table View Cells
Mysteries of Auto Layout, Part 1 (wwdc 2015)
Not sure if it will apply to AutoLayout, although when laying out a cell programmatically, running "layoutIfNeeded()" fixed my cell content stretch issue.
layoutIfNeeded was ran at the end of a configure method, used to map values (view model) to UI objects (views)

With automatic UITableViewCell height in iOS 8, is it possible for it to work if the cell's contents are embedded in a UIView?

My UITableViewCell subclass has several UILabels in it of varying length, and with iOS 8 and Auto Layout constraints in the cell the height is now automatically configured and cell heights can be dynamic.
However I want to embed all the contents of the cell in another UIView. Is it possible for the cell's height to still be dynamic? As in the UIView that the cell contents are embedded in will grow and shrink automatically based on the content and thus the cell will as well? Is this possible?
Dynamic height works by performing an Autolayout pass on the cell's content view. As long as the constraints are in place for a height to be calculated, the specific view hierarchy should be irrelevant.

Resources