Ios 不同宽度的UITableViewCell自动布局

Ios 不同宽度的UITableViewCell自动布局,ios,objective-c,uitableview,uilabel,autolayout,Ios,Objective C,Uitableview,Uilabel,Autolayout,我在故事板中设置了一个UITableViewCell,它有两个标签,设置如下: ----------------------- | ------------------- | | | Label 1 | | | ------------------- | | ------------------- | | | Label 2 | | | ------------------- | ----------------------- 标签1在顶部、左侧和右侧具有固定

我在故事板中设置了一个UITableViewCell,它有两个标签,设置如下:

-----------------------
| ------------------- |
| |     Label 1     | |
| ------------------- |
| ------------------- |
| |     Label 2     | |
| ------------------- |
-----------------------
  • 标签1在顶部、左侧和右侧具有固定的15px约束 利润。内容拥抱(H:251,V:251)。抗压强度(H:750,V:750)
  • 标签2在底部、左侧和右侧具有固定的15px约束 右边距。内容拥抱(H:251,V:251)。抗压强度(H:750,V:751)
  • 标签1对标签2有固定的1px约束
单元格的高度计算如下:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int width = tableView.bounds.size.width - 30;

    NSString *label1Text = ....;
    NSString *label2Text = ....;

    int label1Height = ceilf([label1Text boundingRectWithSize:CGSizeMake(width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17.0]} context:nil].size.height);
    int label1Height = ceilf([label2Text boundingRectWithSize:CGSizeMake(width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17.0]} context:nil].size.height);

    return 15 + label1Height + 1 + label2Text + 15;
}
这对于故事板模板的宽度(例如320px)非常有效。当UITableViewController视图宽度变大(例如500px+)时,单元格采用正确的高度,但是标签1对于其内容来说太大(跨越1行文本超过2行),标签2被挤压(跨越2行文本进入1行)

但是,如果我在情节提要中调整UITableViewController的大小(例如,调整到500px宽)并更新标签的帧(保持相同的约束),则加载视图时,它在500px宽时看起来非常完美,在320px宽时则非常糟糕


有人(对自动布局有更多的了解)能解释一下吗

我假设每个标签都有多行文本。UILabel需要知道它们的宽度,然后才能在返回内部内容大小时给出准确的高度。通过设置
preferredMaxLayoutWidth
可以实现预期的行为,它可能有一个明显的限制:使用自动布局的全部意义在于,您不一定需要或不想知道确切的值

您可以手动计算(如果它不总是固定值)在某个点上所需的标签。这对我来说是一个笨拙的解决方案

我更喜欢创建一个UILabel子类,它只覆盖
layoutSubviews
,可以在布局时自动配置它的
preferredMaxLayoutWidth

// EBTSmartWidthLabel.h

#import <UIKit/UIKit.h>

@interface EBTSmartWidthLabel : UILabel

@end
代码首先将
preferredMaxLayoutWidth
设置为0.0f,这使得UILabel尽可能宽。然后它执行实际布局,宽度将受到自动布局约束的限制。然后,它获取宽度(在您的情况下,宽度应该是最宽的),并使
preferredMaxLayoutWidth
变宽,然后再次执行布局

这不一定是最有效的方法,在一些罕见的/复杂的/人为的情况下,可能会导致大量的重新布局,但我已经用它取得了很好的效果

如果您使用的是故事板/接口Bulder,则可以在UILabel上设置自定义类,这将允许它使用此自定义类


如果您正在使用iOS7+,请尝试

    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
}
而不是

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
}

请发布问题的屏幕截图。这是自动布局和标签的主要难点。UILabel在默认情况下应该是这样的,或者是可以配置的。谢谢Neil。超级灵活的解决方案。像做梦一样工作,方法令人眩晕!
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
}