包含 UITableView 的 UITableViewCell 的自适应高度
Adaptive height for UITableViewCell containing an UITableView
我有一个包含静态行的 UITableView
(我们称之为 table1
)。第一行包含另一个 UITableView
(table2
),从 Internet 上的 XML 文件动态填充,该文件在 之后完成创建,因为异步。只有在请求完成后 table2
才会创建并添加到单元格的 contentView
(否则会提示错误文本作为单元格的标签)。
table2
由折叠的部分组成,这些部分在交互时展开,因此确实改变了 table2
.
的 contentSize
/height
我想要实现的是让 table1
的单元格在 2 个关键点动态调整大小:1 当网络请求完成时,这意味着当table被创建并添加为子视图,2当table2
的一段被交互时,使得table1
的高度发生变化; table1
单元格应遵循并执行完全相同的高度变化。
我到处搜索并尝试了很多东西,但没有任何效果,而且我已经被困了好几天。
这是我试过的方法:
- 重写 (
estimated
)heightForRowAtIndexPath:
:没用,因为它只调用一次并且在添加 table2
之前
- 更改
UITableViewAutomaticDimension
和 estimatedRowHeight
:默认完成
- 使用
NSLayoutConstraint
秒,在 updateConstraints
内或 table2
之后创建
- 玩
intrinsicContentSize
和 invalidateIntrinsicContentSize:
- 使用
reloadRowsAtIndexPaths:withRowAnimation:
...但没有任何效果,我觉得我已经尝试了所有方法
关于约束,我试过类似的东西:
table2.top
= contentView.top
= cell.top
(前导和尾随相同)
cell.bottom
= contentView.bottom
= table2.bottom
(还有身高)
编辑 1:
我的代码:
// 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
(除了常规代码外,与我的问题无关)
编辑 2:
“样机:”
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
对于(2)和(3),红线是我想要的 table2
和单元格的高度。在这个 MRE 中,table2
与 table1
的其余部分重叠,但我当然希望 table1
的单元格之间保持相同的间距,table1
必须随着单元格的增长而增长。
谢谢!
因此,在 DonMag 的帮助下,我重新考虑了我的问题。我的想法是在我的单元格中嵌入一个完整的 table:相反,他们建议使用 小节 。一个link值千字:
github.com/DonMag/SubSectionsDemo
如果你想进一步解释它是如何工作的,让我解释一下。基本上,这个想法是创建 2 种你想要“模拟”你的嵌入式 table 的单元格:(sub)headers & (sub)cells。它们都是属于您 table1
部分的单元格,具有 2 种不同的外观。
然后,要重新创建折叠效果,您必须处理单元格选择,但 仅适用于 tableView:didSelectRowAtIndexPath:
.
中的子标题单元格
单元折叠是通过重新加载数据然后添加到 table1
部分来完成的,在重新加载期间,只有实际上没有折叠的子单元,以及所有子headers.
希望它足够清楚,可以帮助您理解上面 GitHub.
上的代码
不幸的是,我不会使用这个 as-is,因为我确实使用了 UITableViewController
的一个特殊子类,其行为略有不同。我会尝试尽可能多地调整 DonMag 的代码以适应我的使用,但这个想法本身会对我有很大帮助。
我有一个包含静态行的 UITableView
(我们称之为 table1
)。第一行包含另一个 UITableView
(table2
),从 Internet 上的 XML 文件动态填充,该文件在 之后完成创建,因为异步。只有在请求完成后 table2
才会创建并添加到单元格的 contentView
(否则会提示错误文本作为单元格的标签)。
table2
由折叠的部分组成,这些部分在交互时展开,因此确实改变了 table2
.
contentSize
/height
我想要实现的是让 table1
的单元格在 2 个关键点动态调整大小:1 当网络请求完成时,这意味着当table被创建并添加为子视图,2当table2
的一段被交互时,使得table1
的高度发生变化; table1
单元格应遵循并执行完全相同的高度变化。
我到处搜索并尝试了很多东西,但没有任何效果,而且我已经被困了好几天。
这是我试过的方法:
- 重写 (
estimated
)heightForRowAtIndexPath:
:没用,因为它只调用一次并且在添加table2
之前 - 更改
UITableViewAutomaticDimension
和estimatedRowHeight
:默认完成 - 使用
NSLayoutConstraint
秒,在updateConstraints
内或table2
之后创建 - 玩
intrinsicContentSize
和invalidateIntrinsicContentSize:
- 使用
reloadRowsAtIndexPaths:withRowAnimation:
...但没有任何效果,我觉得我已经尝试了所有方法
关于约束,我试过类似的东西:
table2.top
= contentView.top
= cell.top
(前导和尾随相同)
cell.bottom
= contentView.bottom
= table2.bottom
(还有身高)
编辑 1:
我的代码:
// 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
(除了常规代码外,与我的问题无关)
编辑 2:
“样机:”
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
对于(2)和(3),红线是我想要的 table2
和单元格的高度。在这个 MRE 中,table2
与 table1
的其余部分重叠,但我当然希望 table1
的单元格之间保持相同的间距,table1
必须随着单元格的增长而增长。
谢谢!
因此,在 DonMag 的帮助下,我重新考虑了我的问题。我的想法是在我的单元格中嵌入一个完整的 table:相反,他们建议使用 小节 。一个link值千字:
github.com/DonMag/SubSectionsDemo
如果你想进一步解释它是如何工作的,让我解释一下。基本上,这个想法是创建 2 种你想要“模拟”你的嵌入式 table 的单元格:(sub)headers & (sub)cells。它们都是属于您 table1
部分的单元格,具有 2 种不同的外观。
然后,要重新创建折叠效果,您必须处理单元格选择,但 仅适用于 tableView:didSelectRowAtIndexPath:
.
中的子标题单元格
单元折叠是通过重新加载数据然后添加到 table1
部分来完成的,在重新加载期间,只有实际上没有折叠的子单元,以及所有子headers.
希望它足够清楚,可以帮助您理解上面 GitHub.
不幸的是,我不会使用这个 as-is,因为我确实使用了 UITableViewController
的一个特殊子类,其行为略有不同。我会尝试尽可能多地调整 DonMag 的代码以适应我的使用,但这个想法本身会对我有很大帮助。