5

在 SO 和其他地方有很多关于如何根据子视图的大小计算 UITableView 行的必要高度的好信息。典型的例子,也是我在这里应用的例子,是一个包含可变长度文本标签的单元格。

在此处输入图像描述

通常的建议是sizeWithFont:constrainedToSize:lineBreakMode:在 tableview 的heightForRowAtIndexPath:. 但是我见过的大多数示例都使用基于标签已知宽度的“魔术”数字。

CGSize constraint = CGSizeMake(224.0, MAXFLOAT); //224 is known to be the width available
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];

一些更好的示例可能会使用 tableview 的边界,然后为单元格中的其他视图减去幻数或常量,这至少更清晰一些(如果边界在旋转等时发生变化,效果会更好)。

CGSize constraint = CGSizeMake(self.tableview.bounds.size.width - 20 - 10 - 36 - 20, MAXFLOAT); //each non-label width subtracted
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];

这是常见的方法,但似乎缺乏。谁说其他单元格子视图的宽度,甚至字体,保证不会改变(或者总是在两个地方都努力改变)?

我决定我宁愿让细胞负责提供这个高度。细胞总是知道它的属性。为了做到这一点,我首先让单元格中的所有布局代码都引用了一些局部常量。然后,我向我的自定义单元格类添加了一个类方法,它可以根据自己的字体和大小常量返回任何给定文本段所需的高度。

+ (CGFloat)heightRequiredForText:(NSString *)text usingWidth:(CGFloat)width
{
    //a class method that tells the caller how much height is needed for the provided text, based on the cell's size and font constants
    CGSize constraintSize = CGSizeMake(width - kMargin - kGap - kMargin - kCheckboxWidth, MAXFLOAT);
    CGRect bounds = [text boundingRectWithSize:constraintSize
                                                options:NSStringDrawingUsesLineFragmentOrigin
                                             attributes:@{NSFontAttributeName:self.labelFont}
                                                context:nil];
    return bounds.size.height;
}

这允许 UITableViewController 简单地提供文本和当前边界的宽度,(即 tableview 的宽度)。可以在单元格子类中更改字体和布局,并且一切都继续“正常工作”。

问题 1

顺便说一句,这合理吗?有没有更好的方法来实现同样的目标?

问题2

这是我在使用这种(以及更标准的)方法时遇到的主要问题。当单元格处于其编辑模式时,标签的宽度会发生变化以适应编辑附件。由于行高是恒定的,并且标签使用自动布局,因此它的高度会增加。

在此处输入图像描述

所需的行为是标签的高度保持不变,必要时应使用截断。

我在哪里以及如何实现这一点?我应该在单元格的 setEditing: 中做些什么吗?也许添加另一个约束来限制高度,并打开截断,在编辑时应用相反的 == NO?“滑动删除”模式怎么样 - 我认为这不会触发 setEditing?layoutSubview 怎么样 - 我可以在那里做点什么吗?

4

1 回答 1

1

我尝试了很多东西——我得到的最接近的是覆盖 layoutSubviews,测试用户是否已切换到编辑模式,如果是,则首先捕获标签的固有高度,然后添加一个临时约束来强制执行它(然后在退出编辑模式)。除了一些边缘情况外,它运行良好。

但后来我开始更多地考虑自动布局。我想达到什么目的?我不希望标签在宽度减小时变高。这是一个非常简单的约束:

[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.label
                                                                    attribute:NSLayoutAttributeHeight
                                                                    relatedBy:NSLayoutRelationLessThanOrEqual
                                                                       toItem:self.contentView
                                                                    attribute:NSLayoutAttributeHeight
                                                                   multiplier:1
                                                                     constant:0]];

添加这个额外的约束效果很好。请注意,我还将换行模式切换为在编辑时截断:

在此处输入图像描述

于 2013-08-20T22:57:45.220 回答