在计算UITableViewCell高度(所有样式)时,Autolayout忽略多行detailTextLabel [英] Autolayout ignores multi-line detailTextLabel when calculating UITableViewCell height (all styles)

查看:247
本文介绍了在计算UITableViewCell高度(所有样式)时,Autolayout忽略多行detailTextLabel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我试图使用内置的UITableViewCell样式 - 特别是UITableViewCellStyleSubtitle - 使用(单个)行 textLabel 多行 detailTextLabel 。但是(自动)计算的单元格高度始终太短,并且似乎忽略了超过1行细节。

So I'm trying to use the built-in UITableViewCell styles - specifically UITableViewCellStyleSubtitle - with a (single) line textLabel but multiline detailTextLabel. But the (auto) calculated cell height is consistently too short, and appears to ignore that there is more than 1 line of detail.

我尝试过使用numberOfLines = 0 ,estimatedRowHeight,UITableViewAutomaticDimension,preferredMaxWidthLayout等,但在所有排列中的行为 - 实际上对于所有 UITableViewCell样式 - 是否显示UITableViewAutomaticDimension单元格高度计算将正确地考虑多行 textLabel (yay!),但错误地认为 detailTextlabel 最多是单行(nay!)。因此,具有多行detailTextLabel的单元格太短,因此单元格内容溢出单元格的顶部和底部。

I've tried using numberOfLines=0, estimatedRowHeight, UITableViewAutomaticDimension, preferredMaxWidthLayout, etc, but in all the permutations the behavior - indeed for all the UITableViewCell styles - is it appears the UITableViewAutomaticDimension cell height calculation will correctly account for a multiline textLabel (yay!), but incorrectly assumes the detailTextlabel is at most single line (nay!). Consequently, cells with a multiline detailTextLabel are too short, and hence the cell content spills over the top and bottom of the cell.

我发布了一个快速测试应用程序,在GitHub上显示此行为此处。添加额外的文本行很好 - 所有单元格样式的高度适当增加以适应 - 但添加额外的细节线不会改变单元格高度,并且很快会导致内容溢出;文本+细节本身正确布局,并且一起正确地居中在单元格的中间(因此在这种意义上,layoutSubviews正常工作),但整体单元格高度本身不变。

I've posted a quick test app showing this behavior on GitHub here. Adding additional lines of text is fine - all the cell styles appropriately increase in height to accommodate - but adding additional lines of detail does nothing to change the cell height, and quickly causes the content to spill over; the text+detail are themselves laid out correctly, and together centered correctly over the middle of the cell (so in that sense layoutSubviews is working correctly), but the overall cell height itself is unchanged.

几乎看起来没有真正的顶级& cell.contentView和标签之间的底部约束,而是直接从(可能是多行)textLabel和(只有单行)detailTextLabel的高度计算单元格高度,然后所有内容都集中在中间细胞...再次,多行textLabel很好,我在textLabel和detailTextLabel之间没有任何不同,但只有前者(正确)调整单元格高度。

It almost seems like there are no actual top & bottom constraints between the cell.contentView and the labels, and instead the cell height is being calculated directly from the height of the (possibly multi-line) textLabel and (only single-line) detailTextLabel, and then everything is centered over the middle of the cell... Again, multiline textLabel is fine, and I'm doing nothing different between the textLabel and detailTextLabel, but only the former (correctly) adjusts the cell height.

所以我的问题是,如果可以使用内置的UITableViewCell样式可靠地显示多行 detailTextLabels ,或者它根本不可能而且您需要创建而是一个自定义子类? [或者,几乎等同地,不必覆盖子类中的layoutSubviews并手动重新连接所有约束]。

So my question is, if it is possible to use the built-in UITableViewCell styles to reliably display multiline detailTextLabels, or is it simply not possible and you need to create a custom subclass instead? [or, almost equivalently, without having to override layoutSubviews in a subclass and rewire all the constraints manually].

[4 2016年5月]结论:从iOS9开始,多行detailTextLabels无法按预期使用UITableViewAutomaticDimension;单元格将始终太短,文本/细节将溢出顶部和底部。您必须自己手动计算正确的单元格高度,或者创建和布局您自己的等效自定义UITableViewCell子类,或者(请参阅下面的答案)子类UITableViewCell并修复 systemLayoutSizeFittingSize:withHorizo​​ntalFittingPriority:verticalFittingPriority:返回正确的高度[推荐]

[4 May 2016] Conclusion: as of iOS9 multi-line detailTextLabels dont work as expected with UITableViewAutomaticDimension; the cell will be consistently too short and the text/detail will spill over the top and bottom. Either you must manually compute the correct cell height yourself, or create and layout your own equivalent custom UITableViewCell subclass, or (see my answer below) subclass UITableViewCell and fix systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: to return the correct height [recommended]

推荐答案

进一步调查(参见 UITableViewCellTest )表示当启用 UITableViewAutomaticDimension 时,系统调用 -systemLayoutSizeFittingSize:withHorizo​​ntalFittingPriority:verticalFittingPriority:来计算单元格高度,并且这几乎忽略了detailTextLabel在其计算中的高度(bug!?)。因此,对于 UITableViewCellStyleSubtitle ,单元格高度总是太短[单行 detailTextLabel 可能不会完全溢出单元格,但这仅仅是因为现有的上边距和下边距],对于 UITableViewCellStyleValue1 UITableViewCellStyleValue2 ,只要 detailTextLabel 更高(例如更多行),高度就会太短 textLabel 。这对于没有detailTextLabel的 UITableViewCellStyleDefault 来说都是没有实际意义。

Further investigations (see UITableViewCellTest) indicate that when UITableViewAutomaticDimension is enabled the system calls -systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: to calculate the cell height, and that this pretty much 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 [a single-line detailTextLabel may not quite spill over the cell, but that's only because of the existing top and bottom margins], and for UITableViewCellStyleValue1 or UITableViewCellStyleValue2 the height will be too short whenever the detailTextLabel is taller (eg more lines) than the textLabel. This is all a moot point for UITableViewCellStyleDefault which has no detailTextLabel.

我的解决方案是子类化并修复:

My solution was to subclass and fix with:

- (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;
}

在视图控制器中:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.tableView.estimatedRowHeight = 44.0;
    self.tableView.rowHeight = UITableViewAutomaticDimension;
}

您可以从此处提取完整的子类: MultilineTableViewCell

You can pull the full subclass from here: MultilineTableViewCell

到目前为止,此修复程序似乎运行良好,并且让我成功地使用带有多行文本和细节的内置UITableViewCellStyles,在具有动态类型支持的自定义单元格中。这避免了在 tableView:heightForRowAtIndexPath:中手动计算所需单元格高度的麻烦(和混乱),或者必须创建自定义单元格布局。

So far this fix appears to work well, and has let me successfully use the built-in UITableViewCellStyles with multiline text and details, in self-sizing cells with dynamic type support. This avoids the trouble (and mess) of manually computing the desired cell heights in tableView:heightForRowAtIndexPath:, or having to create custom cell layouts.

[(部分)在iOS11中固定]

Apple 终于修复了此错误iOS11(但仅适用于UITableViewCellStyleSubtitle)。我已经更新了我的解决方案,只对11之前的设备应用了必要的修正(否则你最终会得到额外的空间顶部和底部!)。

Apple finally fixed this bug in iOS11 (but apparantly only for UITableViewCellStyleSubtitle). I've updated my solution to only apply the necessary correction to pre-11 devices (otherwise you'll end up with extra space top and bottom of your cell!).

这篇关于在计算UITableViewCell高度(所有样式)时,Autolayout忽略多行detailTextLabel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆