I have an UITableView
(let's call it table1
) which contains static rows. The first row contains another UITableView
(table2
), populated dynamically from an XML file on the internet, which is completed after the cell is being created, because asynchronous. table2
is created and added to cell's contentView
only once the request is done (else an error text is prompted as cell's label).
table2
is made of collapsed sections that are expanded when interacted, which thus do change the contentSize
/height
of the table2
.
What I want to achieve is to make the cell of table1
resize dynamically at 2 key points: 1 when the web request is done, which means when the table is created and added as subview, and 2 when a section of table2
is interacted, which makes the height of table1
change; table1
cell should follow and do exactly the same height variation.
I've searched everywhere and tried tons of things, but nothing ever worked, and I've been stuck for days.
Here's what I've tried:
- Overriding (
estimated
)heightForRowAtIndexPath:
: useless as it's only called once and beforetable2
is added - Changing
UITableViewAutomaticDimension
andestimatedRowHeight
: done by default - Using
NSLayoutConstraint
s, withinupdateConstraints
or aftertable2
creation - Playing with
intrinsicContentSize
andinvalidateIntrinsicContentSize:
- Using
reloadRowsAtIndexPaths:withRowAnimation:
...but nothing worked, and I feel I've tried everything
About the constraints, I tried something like:
table2.top
= contentView.top
= cell.top
(same for leading & trailing)
cell.bottom
= contentView.bottom
= table2.bottom
(also with height)
EDIT 1:
My code:
// Cell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.openSection = -1; // reports which section of table2 is open
SPDSpinnerView *spinner = [[SPDSpinnerView alloc] initWithFrame:self.frame]; // view with UIActivityIndicator & text
spinner.label.text = @"Loading...";
[self addSubview:spinner];
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
[self loadDataWithCompletion:^(BOOL success) {
// Remove spinner
for (UIView *view in [self subviews]) {
if ([view isKindOfClass:[SPDSpinnerView class]]) [view removeFromSuperview];
}
// Handle result
if (success) {
// Add table view when done
self.table2 = [[UITableView alloc] initWithFrame:self.frame style:UITableViewStylePlain];
self.table2.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
[self.table2 registerClass:[SPDChangelogHeaderView class] forHeaderFooterViewReuseIdentifier:@"headerView"]; // custom tappable header for collapsible sections
self.table2.scrollEnabled = NO;
self.table2.delegate = self;
self.table2.dataSource = self;
self.table2.translatesAutoresizingMaskIntoConstraints = NO;
[UIView transitionWithView:self.contentView duration:.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
[self.contentView addSubview:self.table2];
// FIXME: fit table2 in cell
} completion:nil];
} else {
self.textLabel.text = @"Error loading data";
}
}];
}
return self;
}
// delegates, touch handler for table2, and data loader
(nothing else related to my problem aside from usual code)
EDIT 2:
"Mockups:"
What it looks like currently
What I want it to be at step 1 (after data loading)
What I want it to be when inner sections are collapsed or expanded
For (2) and (3), red lines are the height I want for both table2
and the cell. In this MRE, table2
overlaps the rest of table1
but I want of course to keep the same spacing between cells of table1
, table1
must grow as the cell does.
Thank you!
CodePudding user response:
So, with the kind help of DonMag, I've reconsidered my issue. My idea was to embed a whole table in my cell: instead, they proposed to use subsections. A link is worth thousand words:
github.com/DonMag/SubSectionsDemo
If you want further explanation on how it works, let me explain. Basically, the idea is to create 2 kinds of cells you want to "simulate" your embedded table with: (sub)headers & (sub)cells. They will both be cells belonging to the section of your table1
, with 2 different looks.
Then, to recreate the collapsing effect, you have to handle cells selection but only for subheader cells in tableView:didSelectRowAtIndexPath:
.
Cell collapsing is done by reloading data and then adding to table1
section, during the reloading, only subcells that are not virtually collapsed, and all the subheaders.
Hope it was clear enough to help you understand the code above on GitHub.
Unfortunately I won't be using this as-is because I do use a special subclass of UITableViewController
whose behavior is slightly different. I'll try to adapt as much DonMag's code as possible to my use, but the idea by itself will greatly help me.