tir*_*tea 11 uitableview ios autolayout
所以我试图使用内置的UITableViewCell样式 - 特别是UITableViewCellStyleSubtitle - 与(单)行textLabel但多行 detailTextLabel.但是(自动)计算的单元格高度始终太短,并且似乎忽略了超过1行细节.
我已经尝试过使用numberOfLines = 0,estimatedRowHeight,UITableViewAutomaticDimension,preferredMaxWidthLayout等,但在所有排列行为中 - 实际上对于所有 UITableViewCell样式 - 看来UITableViewAutomaticDimension单元格高度计算将正确地考虑多行textLabel(耶! ),但错误地假设detailTextlabel最多是单行(nay!).因此,具有多线detailTextLabel的细胞太短,因此细胞内容溢出细胞的顶部和底部.
我发布了一个快速测试应用程序,在这里显示GitHub上的这种行为.添加额外的文本行很好 - 所有单元格样式的高度适当增加以适应 - 但添加额外的细节行不会改变单元格高度,并且很快会导致内容溢出; 文本+细节本身正确布局,并且一起正确地居中在单元格的中间(因此在这种意义上,layoutSubviews正常工作),但整体单元格高度本身不变.
看起来cell.contentView和标签之间几乎没有实际的顶部和底部约束,而是直接从(可能是多行)textLabel和(只有单行)detailTextLabel的高度计算单元格高度.然后一切都集中在单元格的中间...再次,多行textLabel很好,我在textLabel和detailTextLabel之间没有任何不同,但只有前者(正确)调整单元格高度.
所以我的问题是,如果可以使用内置的UITableViewCell样式来可靠地显示多行 detailTextLabels,或者它根本不可能而你需要创建一个自定义子类呢?[或者,几乎等效地,不必覆盖子类中的layoutSubviews并手动重新连接所有约束].
[2016年5月4日]结论:从iOS9开始,多行detailTextLabels无法按预期使用UITableViewAutomaticDimension; 单元格将始终太短,文本/细节将溢出顶部和底部.您必须自己手动计算正确的单元格高度,或者创建和布局您自己的等效自定义UITableViewCell子类,或者(请参阅下面的答案)子类UITableViewCell并修复systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:以返回正确的高度[推荐]
tir*_*tea 20
进一步的研究(参见UITableViewCellTest)表明,当启用UITableViewAutomaticDimension时,系统调用-systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:计算单元格高度,并且这几乎忽略了计算中detailTextLabel的高度(bug!?).因此,对于UITableViewCellStyleSubtitle,单元格高度总是太短[单行detailTextLabel可能不会完全溢出单元格,但这只是因为现有的顶部和底部边距],而对于UITableViewCellStyleValue1或UITableViewCellStyleValue2的高度只要detailTextLabel比textLabel更高(例如更多行),它就会太短.这对于没有detailTextLabel的UITableViewCellStyleDefault来说都是一个有争议的问题.
我的解决方案是子类化并修复:
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize
withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority
verticalFittingPriority:(UILayoutPriority)verticalFittingPriority
{
// Bug finally fixed in iOS 11
if ([UIDevice.currentDevice.systemVersion compare:@"11" options:NSNumericSearch] != NSOrderedAscending) {
return [super systemLayoutSizeFittingSize:targetSize
withHorizontalFittingPriority:horizontalFittingPriority
verticalFittingPriority:verticalFittingPriority];
}
[self layoutIfNeeded];
CGSize size = [super systemLayoutSizeFittingSize:targetSize
withHorizontalFittingPriority:horizontalFittingPriority
verticalFittingPriority:verticalFittingPriority];
CGFloat detailHeight = CGRectGetHeight(self.detailTextLabel.frame);
if (detailHeight) { // if no detailTextLabel (eg style = Default) then no adjustment necessary
// Determine UITableViewCellStyle by looking at textLabel vs detailTextLabel layout
if (CGRectGetMinX(self.detailTextLabel.frame) > CGRectGetMinX(self.textLabel.frame)) { // style = Value1 or Value2
CGFloat textHeight = CGRectGetHeight(self.textLabel.frame);
// If detailTextLabel taller than textLabel then add difference to cell height
if (detailHeight > textHeight) size.height += detailHeight - textHeight;
} else { // style = Subtitle, so always add subtitle height
size.height += detailHeight;
}
}
return size;
}
Run Code Online (Sandbox Code Playgroud)
并在视图控制器中:
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 44.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
Run Code Online (Sandbox Code Playgroud)
您可以从此处提取完整的子类:MultilineTableViewCell
到目前为止,这个修复似乎运行良好,并让我成功地使用内置的UITableViewCellStyles与多行文本和细节,在具有动态类型支持的自定义单元格中.这避免了手动计算所需单元高度tableView:heightForRowAtIndexPath:或必须创建自定义单元布局的麻烦(和混乱).
[(部分)在iOS11中固定]
Apple 最终修复了iOS11中的这个错误(但仅适用于UITableViewCellStyleSubtitle).我已经更新了我的解决方案,只对11之前的设备进行了必要的修正(否则你最终会在你的单元的顶部和底部留出额外的空间!).
@tiritea 在 Swift 3 中的回答(再次感谢!:D)
// When UITableViewAutomaticDimension is enabled the system calls
// -systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: to calculate the cell height.
// Unfortunately, it ignores the height of the detailTextLabel in its computation (bug !?).
// As a result, for UITableViewCellStyleSubtitle the cell height is always going to be too short.
// So we override to include detailTextLabel height.
// Credit: http://stackoverflow.com/a/37016869/467588
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
self.layoutIfNeeded()
var size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
if let textLabel = self.textLabel, let detailTextLabel = self.detailTextLabel {
let detailHeight = detailTextLabel.frame.size.height
if detailTextLabel.frame.origin.x > textLabel.frame.origin.x { // style = Value1 or Value2
let textHeight = textLabel.frame.size.height
if (detailHeight > textHeight) {
size.height += detailHeight - textHeight
}
} else { // style = Subtitle, so always add subtitle height
size.height += detailHeight
}
}
return size
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2584 次 |
| 最近记录: |