我有一个带有单元格的 TableView ,有时它有一个可选的 UI 元素,有时它必须被删除。 根据元素,标签会调整大小。
初始化单元格时,它比以后要窄。当我将数据设置到标签中时,从 cellForRowAtIndexPath:
if (someFlag) {
// This causes layout to be invalidated
[flagIcon removeFromSuperview];
[cell setNeedsLayout];
}
之后,单元格返回到表格 View ,并显示出来。但是,此时的文本标签已调整其宽度,但未调整高度。高度在一秒钟左右后得到调整,当所有单元格都已显示时,抖动清晰可见。
重要说明,这仅在最初创建前几个单元格时出现。一旦它们被重用,一切都很好,因为可选 View 被删除并且标签已经根据以前的用法正确调整大小。
为什么单元格在 setNeedsLayout
之后但在显示之前没有完全重新布局? UIKit 不应该在显示之前检查无效布局吗?
如果我这样做
if (someFlag) {
[flagIcon removeFromSuperview];
[cell layoutIfNeeded];
}
一下子就全部调整好了,但是写代码的方式似乎不对,我觉得我还漏掉了其他东西。
关于如何创建单元格的更多代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
ProfileCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
[cell setData:model.items[indexPath.row] forMyself:YES];
return cell;
}
// And in ProfileCell:
- (void)setData:(Entity *)data forMyself:(BOOL)forMe
{
self.entity = data;
[self.problematicLabel setText:data.attributedBody];
// Set data in other subviews as well
if (forMe) {
// This causes layouts to be invalidated, and problematicLabel should resize
[self.reportButton removeFromSuperview];
[self layoutIfNeeded];
}
}
此外,如果重要的话,在 Storyboard单元格中看起来像这样,一旦移除标志图标,可选约束就会接管:
最佳答案
我同意调用 layoutIfNeeded
似乎是错误的,即使它适用于您的情况。但我怀疑你错过了什么。虽然我还没有对这种方式进行任何研究,但根据我在表格单元格中使用自动布局的经验,进行动态布局是有点错误的。也就是说,在运行时向单元格移除或添加 subview 时,我会看到不稳定的布局。
如果您正在寻找替代策略(使用自动布局),您可以继承 UITableViewCell
并覆盖 layoutSubviews
。自定义表格单元格可以在其公共(public) API 中公开一个标志,该标志可以在 tableView:cellForRowAtIndexPath:
的实现中设置。单元格的 layoutSubviews
方法将使用标志来确定它是否应该包含可选的 UI 元素。但是,我不保证这会消除问题。
第二个策略是设计两个单独的单元格类型,并根据需要在 tableView:cellForRowAtIndexPath:
中交换这两个单元格类型。
关于ios - setNeedsLayout 仅在显示后重新布局单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20925247/