I want to have self sizing cells within a tableview with self sizing cells. But on first initialisation some cells are not correct. After a scroll to the bottom and the cells will display again the cell size is correct. In the screenshot you can see that the top 2 cells have a white space at the bottom and the third one doesn't. They should all look like the third one.
This is the issue in my main project.
Screenshot
The problem with automatically sizing cells inside automatically sized cells is a bit tricky because you have to understand how it works. UITableView works with estimates most of the time. It usually does not calculate the contentSize precisely because to calculate it precisely, it has to first instantiate every cell, layout it and then calculate its size.
The precise values are calculated only for cells that are displayed (visible in current scroll frame).
The tricky part is that the inner cells (inside your outer cell) are not displayed until the outer cell is displayed therefore the outer cell does not have size calculated correctly. Also note that UITableView does not automatically update cell heights unless explicitly said to do so.
The solution, if you really have to do this, is to calculate the height of the outer cell correctly before it is displayed and manually set a height constraint.
If you know the height (from data source), it's easy. If you actually need to calculate the height of the inner table, you can do something like this:
// make the table high enough to display all cells
innerTableHeightConstraint.constant = 2000
// reload table
innerTable.reloadData()
// force layout
innerTable.layoutIfNeeded()
// now the contentSize is correctly calculated
innerTableHeightConstraint.constant = innerTable.contentSize.height
The whole concept is tricky and ideally you should prefer using UICollectionView or table sections. When you are using inner table views, there won't be any cell reuse for the inner tables and your performance will suffer.
You should not wrap UITableView into UITableViewCell, try to use UITableView Sections instead to add an extra depth level to your UITableView.
Related
This illustration shows what i'm trying to do:
The green list is the UITableView where it dynamically adjust it's height based on the number of items inside of it.
Underneath of the UITableView is a button that should follow the UITableView whenever it changes it's height size.
The UIButton should always be beneath the UITableView whatever the size of the UItableView.
I'm currently using autoresizing for UITableView
I have tried to use Autolayout but it seems i can't still find the answer.
i currently have no constraints in the layout.
This boils down to calculating the height of the table view that perfectly fits the cells. Basically you need to measure the size of every cell, then create a height constraint on the table view, and set its constant to the sum of the cells' heights.
Measuring the height of cells is tricky thought. If you only have a few cells (like in your illustrations), you can just instantiate all of them, keep them in an array and use systemLayoutSizeFittingSize to calculate their sizes. If you use multi-line labels, it is also important to set their preferredMaxLayoutWidth to appropriate values.
However, if you have only a few cells (and so cell reuse is not important), stack view is probably a better choice than table view. It's just too tricky to calculate the perfect height of a table view.
I'm working on an app that will populate the tableview based on a web service response. So far the two content types I know I will be getting will be data shown in a textview, and also in a collection view. I've begun implementing Ash Furrow's AFCollectionView. The dynamic sizing for text areas is working, however the collection view is scrolling within a cell height that is even less than my estimatedRowHeight (210.0).
Because the collection view table cell is not correctly resizing is it possible to explicitly set the height for the collectionView cell(s), and let any of the text based cells remain dynamic?
Your self sizing cells use auto-layout to determine what height to be, and that's based on the intrinsic content size of the subviews. But, that's not the only way auto-layout can specify the height of a view. You can add a static height constraint to your cells which contain a collection view.
I've got a layout with nested UITableViews (each UITableViewCell's contentView has as unique child another UITableView).
All the leaf cells are correctly set up with autolayout (in fact, when they are presented in a single table they are displayed ok).
But when they are inside the inner table, the outer table does not calculate the correct heights for cells, leading to their standard height of 44. I'm using
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 260;
for both inner and outer tables.
How can I get the tables to show correct heights with autolayout? (I don't want to override tableView:cellForRowAtIndexPath:, I want autolayout to do the trick).
Thank you in advance
I personally think that nesting tableview is a bad UX experience. Better you'll find a different approach for your users.
Saying that they also lead to different problems, for instance who scroll first etc.
In your case the issue is due to the fact that UITableViewAutomaticDimension simply send to the cell content view -systemLayoutSizeFittingSize(or similar) with UILayoutFittingCompressedSize, that for a scroll view means 0;0 basically your table view is not counted while calculating the cell height.
In my opinion now you have 2 options:
make your calculus manually and cache the result for a faster
scrolling
create a subclass of a UITableView that when asked for its intrinsicContentSize returns a custom size
Really hope this helps.
I have a problem with iOS8 autolayout / resizing. In my app, there is one full-screen table with different cells. Those cells are dynamically sized to resize based on their content using
self.tableView.estimatedRowHeight = 44.0
self.tableView.rowHeight = UITableViewAutomaticDimension
(see appcoda or stack overflow, using same set of constraints, eg. top/left/right/bottom for top label and left/right/bottom for bottom label). Resulting in something like this:
So this works great. Now, I need to add an extra cell that has another table embedded in it. This embedded table has dynamic number of rows, should not be scrollable, but rather should resize its containing cell according to self size. But no matter what I do with constraints, I cannot get the containing cell (highlighted in red) to grow (the table Row#0, Row#1, ... has actually 10 items, but only first two are shown).
The idea is to have something similar to native ios maps' detail, where for example Reviews looks like an embedded dynamically sized table:
I have 3 labels in a UITableViewCell and have the labels set so they will wordwrap. If they word wrap the text goes into the next cell. How do I get AutoLayout to expand the cell based on the content without having to write code in the heightForRowAtIndex method? Isn't there a constraint I can use to automatically adjust the cell based on the contentView?
The cell looks fine if the text doesn't wrap in the label. Once it wraps that is when the problem occurs and I would like to have the cell resize to fit the content and have the same spacing between the bottom label and the bottom as there is between the top and top label.
Unfortunately no, you can't do this. A table view calculates its own total height first and has a fixed idea of the size of each cell as they load, it won't determine it's height from the outside in and it won't let layout constraints change the height of a cell.
If you think about how tables work, with cell reuse, then you couldn't really size the table from its cells without loading in every cell and adding it to the scrollview, and performing a layout pass on the whole thing. That would probably lead to quite poor performance.
You could experiment with populating a "free" cell (i.e a cell you've just instantiated, not added to a table) and laying it out for each row in your datasource when calculating heightForRow.
As you are loading the individual cells, after you fill the labels, but before you load the instance of the cell, check the label height.
Something like:
cell.frame.size.height
If the height is large enough that you know the label has wrapped to two lines, then increase the height of the cell you are about to load.