关于SO和elsewhere有很多关于如何根据子视图的大小计算UITableView行的必要高度的好信息。典型的例子和我在这里应用的例子是一个包含带有可变长度文本的标签的单元格。
通常的建议是使用tableview sizeWithFont:constrainedToSize:lineBreakMode:
中的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 - 我可以在那里做点什么吗?
答案 0 :(得分:1)
我尝试了很多东西 - 我得到的最接近的是覆盖layoutSubviews,测试用户是否已切换到编辑模式,如果是这样,首先捕获标签的内在高度,然后添加临时约束来强制执行它(这是然后在退出编辑模式时删除)。除了少数边缘情况外,它运作良好。
然后我开始考虑更多的自动布局。我想要达到什么目的?当宽度减小时,我不希望标签长得更高。这是一个非常简单的约束:
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.label
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationLessThanOrEqual
toItem:self.contentView
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0]];
添加此附加约束效果很好。请注意,我还会在编辑时将换行符模式切换为截断: