UITableViewCell Autolayout用于不同的宽度

时间:2014-04-14 12:08:48

标签: ios objective-c uitableview uilabel autolayout

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

-----------------------
| ------------------- |
| |     Label 1     | |
| ------------------- |
| ------------------- |
| |     Label 2     | |
| ------------------- |
-----------------------
  • 标签1对顶部,左侧和右侧固定了15px约束 利润率。内容拥抱(H:251,V:25​​1)。耐压缩性(H:750,V:750)。
  • 标签2对底部,左侧和左侧固定了15px约束 右边距。内容拥抱(H:251,V:25​​1)。耐压缩性(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时非常糟糕。

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

2 个答案:

答案 0 :(得分:1)

我假设您打算为每个标签添加多行文本。 UILabels需要知道 的宽度,然后才能在返回内在内容大小时提供准确的高度。预期的行为可以通过设置preferredMaxLayoutWidth来完成,它可能有一个明显的限制:使用自动布局的重点是你不一定需要或想知道确切的值是什么。

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

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

// EBTSmartWidthLabel.h

#import <UIKit/UIKit.h>

@interface EBTSmartWidthLabel : UILabel

@end

然后

// EBTSmartWidthLabel.m

#import "EBTSmartWidthLabel.h"

@implementation EBTSmartWidthLabel

- (void)layoutSubviews
{
    self.preferredMaxLayoutWidth = 0.0f;
    [super layoutSubviews];
    self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);
    [super layoutSubviews];
}

@end

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

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

如果您正在使用Storyboard / Interface Bulder,则可以在UILabel上设置自定义类,这将允许它使用此自定义类。

Custom Class in Interface Builder

答案 1 :(得分:0)

如果您使用的是iOS7 +,请尝试

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

而不是

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