ios - 可变长度标签、tableview 行高和自动布局

标签 ios uitableview uilabel autolayout

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

enter image description here

通常的建议是在 TableView 的 heightForRowAtIndexPath: 中使用 sizeWithFont:constrainedToSize:lineBreakMode:。但我见过的大多数示例都使用基于标签已知宽度的“魔数(Magic Number)”。

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

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

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];

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

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

+ (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 的宽度)。可以在单元格子类中更改字体和布局,一切都继续“正常工作”。

问题一

作为旁注,这合理吗?有没有更好的方法来实现同样的目标?

问题二

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

enter image description here

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

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

最佳答案

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

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

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

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

enter image description here

关于ios - 可变长度标签、tableview 行高和自动布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18342558/

相关文章:

ios - 不显示来自解析的数据

ios - 如何在 Objective-C 中旋转 UIButton 和 UILabel 的文本?

ios - 证书尚未生效

iphone - 在 iPhone 项目中使用 BCTabBarController

objective-c - Objective-C - block 代码不按顺序执行?

ios - UIScrollview 内的 UIView 内的 UILabel 上的 UIGestureRecognizer

swift - 子类化的 UILabel 不显示

ios - 应用程序加载器 : ERROR ITMS-90502

android - Android 中的自定义 URL 处理?你能在 iOS 中做同样的事情吗?

iOS:类似于邮件或消息应用程序的可滚动搜索栏